k 8 s ConfigMapホットアップデート
12734 ワード
コンフィギュレーション・Mapは、コンフィギュレーション・ファイルを格納するためのkubernetesリソース・オブジェクトであり、すべてのコンフィギュレーション・コンテンツがetcdに格納されています.以下では、コンフィギュレーション・Mapの作成と更新の流れ、およびコンフィギュレーション・Mapの更新後にコンテナにマウントされたコンテンツが同期して更新されるかどうかを調べるテストを行います.
このConfigMapの内容を取得します.
ConfigMapの内容はetcdに格納され、etcdに問い合わせます.
v 3バージョンのetcdctl APIを使用することに注意してください.次は出力結果です.
valueは
ConfigMap構造体の定義:
リソースオブジェクトのnamespaceとHTTPリクエストのbodyを設定したRESTfulリクエストによりetcdにConfigMapの構成を格納し、実行後にリクエスト結果をresultに保存して呼び出し元に返す.
ボディの構造に注意
ConfigMap RESTfulリクエストを作成するBodyには、
HTTP要求中の構造体:
ConfigMapを使用してEnvとVolumeをマウントする場合をそれぞれテストします.
次の構成を使用して、nginxコンテナを作成し、ConfigMapを更新した後、コンテナ内の環境変数も更新されるかどうかをテストします.
環境変数の値の取得
コンフィグマップの変更
修正
環境変数の値を再度確認します.
ConfigMapを変更すると、コンテナに注入された環境変数情報が更新されないことが実証されました.
次の構成を使用して、nginxコンテナを作成し、ConfigMapを更新した後、コンテナにマウントされているファイルも更新されるかどうかをテストします.
コンフィグマップの変更
修正
約10秒待って、環境変数の値を再度表示します.
ConfigMap方式でマウントされたVolumeのファイルの内容が
Known Issue:ConfigMapのsubPathをContainerのVolumeとしてマウントしている場合、Kubernetesは自動的なホットアップデートを行いません
ConfigMapの更新は現在、関連するPodのスクロール更新をトリガーするものではなく、pod annotationsを変更することで強制的にスクロール更新をトリガーすることができます.
この例では、
ConfigMapを更新すると、このConfigMapを使用してマウントされたEnvは、 を同期更新しません.このConfigMapでマウントするVolumeのデータを使用するには、 を同期的に更新するには、時間(実測約10秒)がかかる.
ENVはコンテナの起動時に注入され,起動後kubernetesは環境変数の値を変更せず,同じnamespace中のpodの環境変数が累加される.コンテナでコンフィグマップを使用してマウントされている構成を更新するには、podをスクロールして更新することでコンフィグマップの再マウントを強制する必要があります.
テスト例
default
namespaceの下にnginx-config
というConfigMapがあるとします.kubectl
コマンドを使用して取得できます.$ kubectl get configmap nginx-config
NAME DATA AGE
nginx-config 1 99d
このConfigMapの内容を取得します.
kubectl get configmap nginx-config -o yaml
apiVersion: v1
data:
nginx.conf: |-
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
server {
listen 80;
# a test endpoint that returns http 200s
location / {
proxy_pass http://httpstat.us/200;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name api.hello.world;
location / {
proxy_pass http://l5d.default.svc.cluster.local;
proxy_set_header Host $host;
proxy_set_header Connection "";
proxy_http_version 1.1;
more_clear_input_headers 'l5d-ctx-*' 'l5d-dtab' 'l5d-sample';
}
}
server {
listen 80;
server_name www.hello.world;
location / {
# allow 'employees' to perform dtab overrides
if ($cookie_special_employee_cookie != "letmein") {
more_clear_input_headers 'l5d-ctx-*' 'l5d-dtab' 'l5d-sample';
}
# add a dtab override to get people to our beta, world-v2
set $xheader "";
if ($cookie_special_employee_cookie ~* "dogfood") {
set $xheader "/host/world => /srv/world-v2;";
}
proxy_set_header 'l5d-dtab' $xheader;
proxy_pass http://l5d.default.svc.cluster.local;
proxy_set_header Host $host;
proxy_set_header Connection "";
proxy_http_version 1.1;
}
}
}
kind: ConfigMap
metadata:
creationTimestamp: 2017-08-01T06:53:17Z
name: nginx-config
namespace: default
resourceVersion: "14925806"
selfLink: /api/v1/namespaces/default/configmaps/nginx-config
uid: 18d70527-7686-11e7-bfbd-8af1e3a7c5bd
ConfigMapの内容はetcdに格納され、etcdに問い合わせます.
ETCDCTL_API=3 etcdctl get /registry/configmaps/default/nginx-config -w json|python -m json.tool
v 3バージョンのetcdctl APIを使用することに注意してください.次は出力結果です.
{
"count": 1,
"header": {
"cluster_id": 12091028579527406772,
"member_id": 16557816780141026208,
"raft_term": 36,
"revision": 29258723
},
"kvs": [
{
"create_revision": 14925806,
"key": "L3JlZ2lzdHJ5L2NvbmZpZ21hcHMvZGVmYXVsdC9uZ2lueC1jb25maWc=",
"mod_revision": 14925806,
"value": "azhzAAoPCgJ2MRIJQ29uZmlnTWFwEqQMClQKDG5naW54LWNvbmZpZxIAGgdkZWZhdWx0IgAqJDE4ZDcwNTI3LTc2ODYtMTFlNy1iZmJkLThhZjFlM2E3YzViZDIAOABCCwjdyoDMBRC5ss54egASywsKCm5naW54LmNvbmYSvAt3b3JrZXJfcHJvY2Vzc2VzIDE7CgpldmVudHMgeyB3b3JrZXJfY29ubmVjdGlvbnMgMTAyNDsgfQoKaHR0cCB7CiAgICBzZW5kZmlsZSBvbjsKCiAgICBzZXJ2ZXIgewogICAgICAgIGxpc3RlbiA4MDsKCiAgICAgICAgIyBhIHRlc3QgZW5kcG9pbnQgdGhhdCByZXR1cm5zIGh0dHAgMjAwcwogICAgICAgIGxvY2F0aW9uIC8gewogICAgICAgICAgICBwcm94eV9wYXNzIGh0dHA6Ly9odHRwc3RhdC51cy8yMDA7CiAgICAgICAgICAgIHByb3h5X3NldF9oZWFkZXIgIFgtUmVhbC1JUCAgJHJlbW90ZV9hZGRyOwogICAgICAgIH0KICAgIH0KCiAgICBzZXJ2ZXIgewoKICAgICAgICBsaXN0ZW4gODA7CiAgICAgICAgc2VydmVyX25hbWUgYXBpLmhlbGxvLndvcmxkOwoKICAgICAgICBsb2NhdGlvbiAvIHsKICAgICAgICAgICAgcHJveHlfcGFzcyBodHRwOi8vbDVkLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWw7CiAgICAgICAgICAgIHByb3h5X3NldF9oZWFkZXIgSG9zdCAkaG9zdDsKICAgICAgICAgICAgcHJveHlfc2V0X2hlYWRlciBDb25uZWN0aW9uICIiOwogICAgICAgICAgICBwcm94eV9odHRwX3ZlcnNpb24gMS4xOwoKICAgICAgICAgICAgbW9yZV9jbGVhcl9pbnB1dF9oZWFkZXJzICdsNWQtY3R4LSonICdsNWQtZHRhYicgJ2w1ZC1zYW1wbGUnOwogICAgICAgIH0KICAgIH0KCiAgICBzZXJ2ZXIgewoKICAgICAgICBsaXN0ZW4gODA7CiAgICAgICAgc2VydmVyX25hbWUgd3d3LmhlbGxvLndvcmxkOwoKICAgICAgICBsb2NhdGlvbiAvIHsKCgogICAgICAgICAgICAjIGFsbG93ICdlbXBsb3llZXMnIHRvIHBlcmZvcm0gZHRhYiBvdmVycmlkZXMKICAgICAgICAgICAgaWYgKCRjb29raWVfc3BlY2lhbF9lbXBsb3llZV9jb29raWUgIT0gImxldG1laW4iKSB7CiAgICAgICAgICAgICAgbW9yZV9jbGVhcl9pbnB1dF9oZWFkZXJzICdsNWQtY3R4LSonICdsNWQtZHRhYicgJ2w1ZC1zYW1wbGUnOwogICAgICAgICAgICB9CgogICAgICAgICAgICAjIGFkZCBhIGR0YWIgb3ZlcnJpZGUgdG8gZ2V0IHBlb3BsZSB0byBvdXIgYmV0YSwgd29ybGQtdjIKICAgICAgICAgICAgc2V0ICR4aGVhZGVyICIiOwoKICAgICAgICAgICAgaWYgKCRjb29raWVfc3BlY2lhbF9lbXBsb3llZV9jb29raWUgfiogImRvZ2Zvb2QiKSB7CiAgICAgICAgICAgICAgc2V0ICR4aGVhZGVyICIvaG9zdC93b3JsZCA9PiAvc3J2L3dvcmxkLXYyOyI7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHByb3h5X3NldF9oZWFkZXIgJ2w1ZC1kdGFiJyAkeGhlYWRlcjsKCgogICAgICAgICAgICBwcm94eV9wYXNzIGh0dHA6Ly9sNWQuZGVmYXVsdC5zdmMuY2x1c3Rlci5sb2NhbDsKICAgICAgICAgICAgcHJveHlfc2V0X2hlYWRlciBIb3N0ICRob3N0OwogICAgICAgICAgICBwcm94eV9zZXRfaGVhZGVyIENvbm5lY3Rpb24gIiI7CiAgICAgICAgICAgIHByb3h5X2h0dHBfdmVyc2lvbiAxLjE7CiAgICAgICAgfQogICAgfQp9GgAiAA==",
"version": 1
}
]
}
valueは
nginx.conf
プロファイルの内容です.コード#コード#
ConfigMap構造体の定義:
// ConfigMap holds configuration data for pods to consume.
type ConfigMap struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Data contains the configuration data.
// Each key must be a valid DNS_SUBDOMAIN with an optional leading dot.
// +optional
Data map[string]string `json:"data,omitempty" protobuf:"bytes,2,rep,name=data"`
}
staging/src/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go
におけるConfigMapのインタフェース定義:// ConfigMapInterface has methods to work with ConfigMap resources.
type ConfigMapInterface interface {
Create(*v1.ConfigMap) (*v1.ConfigMap, error)
Update(*v1.ConfigMap) (*v1.ConfigMap, error)
Delete(name string, options *meta_v1.DeleteOptions) error
DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error
Get(name string, options meta_v1.GetOptions) (*v1.ConfigMap, error)
List(opts meta_v1.ListOptions) (*v1.ConfigMapList, error)
Watch(opts meta_v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ConfigMap, err error)
ConfigMapExpansion
}
staging/src/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go
でConfigMapを作成する方法は次のとおりです.// Create takes the representation of a configMap and creates it. Returns the server's representation of the configMap, and an error, if there is any.
func (c *configMaps) Create(configMap *v1.ConfigMap) (result *v1.ConfigMap, err error) {
result = &v1.ConfigMap{}
err = c.client.Post().
Namespace(c.ns).
Resource("configmaps").
Body(configMap).
Do().
Into(result)
return
}
リソースオブジェクトのnamespaceとHTTPリクエストのbodyを設定したRESTfulリクエストによりetcdにConfigMapの構成を格納し、実行後にリクエスト結果をresultに保存して呼び出し元に返す.
ボディの構造に注意
// Body makes the request use obj as the body. Optional.
// If obj is a string, try to read a file of that name.
// If obj is a []byte, send it directly.
// If obj is an io.Reader, use it directly.
// If obj is a runtime.Object, marshal it correctly, and set Content-Type header.
// If obj is a runtime.Object and nil, do nothing.
// Otherwise, set an error.
ConfigMap RESTfulリクエストを作成するBodyには、
ObjectMeta
とnamespace
が含まれています.HTTP要求中の構造体:
// Request allows for building up a request to a server in a chained fashion.
// Any errors are stored until the end of your call, so you only have to
// check once.
type Request struct {
// required
client HTTPClient
verb string
baseURL *url.URL
content ContentConfig
serializers Serializers
// generic components accessible via method setters
pathPrefix string
subpath string
params url.Values
headers http.Header
// structural elements of the request that are part of the Kubernetes API conventions
namespace string
namespaceSet bool
resource string
resourceName string
subresource string
timeout time.Duration
// output
err error
body io.Reader
// This is only used for per-request timeouts, deadlines, and cancellations.
ctx context.Context
backoffMgr BackoffManager
throttle flowcontrol.RateLimiter
}
テスト
ConfigMapを使用してEnvとVolumeをマウントする場合をそれぞれテストします.
コンフィグマップでマウントされているEnvを更新
次の構成を使用して、nginxコンテナを作成し、ConfigMapを更新した後、コンテナ内の環境変数も更新されるかどうかをテストします.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: harbor-001.jimmysong.io/library/nginx:1.9
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: env-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
環境変数の値の取得
$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` env|grep log_level
log_level=INFO
コンフィグマップの変更
$ kubectl edit configmap env-config
修正
log_level
の値はDEBUG
です.環境変数の値を再度確認します.
$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` env|grep log_level
log_level=INFO
ConfigMapを変更すると、コンテナに注入された環境変数情報が更新されないことが実証されました.
ConfigMapでマウントされているVolumeを更新
次の構成を使用して、nginxコンテナを作成し、ConfigMapを更新した後、コンテナにマウントされているファイルも更新されるかどうかをテストします.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: harbor-001.jimmysong.io/library/nginx:1.9
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
log_level: INFO
$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` cat /etc/config/log_level
INFO
コンフィグマップの変更
$ kubectl edit configmap special-config
修正
log_level
の値はDEBUG
です.約10秒待って、環境変数の値を再度表示します.
$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` cat /tmp/log_level
DEBUG
ConfigMap方式でマウントされたVolumeのファイルの内容が
DEBUG
になっていることがわかります.Known Issue:ConfigMapのsubPathをContainerのVolumeとしてマウントしている場合、Kubernetesは自動的なホットアップデートを行いません
ConfigMap更新後スクロール更新Pod
ConfigMapの更新は現在、関連するPodのスクロール更新をトリガーするものではなく、pod annotationsを変更することで強制的にスクロール更新をトリガーすることができます.
$ kubectl patch deployment my-nginx --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config": "20180411" }}}}}'
この例では、
.spec.template.metadata.annotations
にversion/config
を追加し、version/config
を変更するたびにスクロール更新をトリガーします.まとめ
ConfigMapを更新すると、
ENVはコンテナの起動時に注入され,起動後kubernetesは環境変数の値を変更せず,同じnamespace中のpodの環境変数が累加される.コンテナでコンフィグマップを使用してマウントされている構成を更新するには、podをスクロールして更新することでコンフィグマップの再マウントを強制する必要があります.