kubernetes in プロダクション! -- cndjp第2回
Post on 21-Jan-2018
72 Views
Preview:
TRANSCRIPT
Kubernetes in プロダクション!#cndjp2
前半戦
前半戦のメニュー
1. 前回の復習
2. ロギング
復習
Kubernetesの全体像
k8sクラスター
>_
kubectl (CLI)
マシンとネットワーク
Kubernetes Objects
• Node
• Pod
• Service
• Label/Label Selector
• Deployment
• ReplicaSet
• DaemonSet
…
Node
• クラスターに属するマシンを表すオブジェクト
• クラスターの管理を担当するマスターノードと、アプリケーションを稼働させるメンバーノードがある
メンバーノード
マスターノード
Pod
• Node内で稼働するコンテナのセット
• 生成/スケールアウト/破棄等のライフサイクルの単位
• 内包する複数のコンテナは、必ず同じノード上で稼働
• 1つのPodに1つのクラスタ内IPが割り当てられる
ポッド
コンテナ
Service
• PodへのTCP/UDPアクセスの制御を行うオブジェクト
• Podへのルーティング、ロードバランシングの役割を持つ
• クラスター外部への公開、クラスター内の通信など、用途に応じて複数のタイプから選択可能
サービス
クラスター外からのリクエスト
Label/Label Selector
• k8sオブジェクトを管理し易いようにグルーピングする仕組み
• Label: • k8sオブジェクトにアタッチで
きるkey/valueペアのセット
• Label Selector:• Labelの設定値の条件を指定す
る情報。条件に該当するものをグループとして識別する
"labels": {"tier" : "frontend","partition" : "customerA"
}
"labels": {"tier" : “backend","partition" : "customerA"
}
"labels": {"tier" : "frontend","partition" : "customerB"
}
Label
Label
partition = customerA
Label Selector
Label/Label Selector
• Serviceがルーティングの対象を識別するためにも利用される
サービス
partition = customerA
クラスター外からのリクエスト
Label/Label Selector
• Serviceがルーティングの対象を識別するためにも利用される
サービス
partition = customerA
クラスター外からのリクエスト
Deployment
• Podのライフサイクル(生成/更新/破棄)を制御するオブジェクト
• Podを起動したり、スケールさせたりするときに、対応するDeploymentに対して操作を行う
デプロイメント
D
ロギング
ロギングのアーキテクチャ
• 標準出力/標準エラー出力をContainer Engine(Docker)のlogging driverがファイルとして出力[^1]
• logrotateツールがローテート
• logging agentがbackendにログを転送• 例)agent → fluentd, backend → Elasticsearch
stdout/stderrを書き出す
log-file.log
logrotate
ローテート
logging agent(e.g. fluentd)
backend(e.g. Elasticsearch)
システムコンポーネントのログ
• SystemコンポーネントにはContainerとして動くものと、そうでないものがある
1. Containerとして動く→ Kubernetes Scheduler, kube-proxy…
2. Containerとして動かない→ kubelet, Docker…
• 1. のログは/var/logに出力される
• 2. のログはsystemdを使う場合はjournaldに、そうでない場合は/var/logに出力される
出力先を複数系統にしたい場合
• ファイルとして複数系統にログ出力
• sidecarコンテナを系統ごとに立て、それぞれがログファイルの内容を標準/標準エラー出力に流す
system.log
logrotate
ローテート
logging agent(e.g. fluentd)
backend(e.g. Elasticsearch)
access.log
YAMLの記述例
kind: Pod…spec:containers:- name: countimage: busyboxargs:
…volumeMounts:- name: varlog
mountPath: /var/log- name: count-log-1image: busyboxargs: [/bin/sh, -c, ‘tail -n+1 -f /var/log/1.log’]volumeMounts:- name: varlog
mountPath: /var/log- name: count-log-2image: busyboxargs: [/bin/sh, -c, ‘tail -n+1 -f /var/log/2.log’]volumeMounts:- name: varlog
mountPath: /var/log…
var/log/配下のログファイルをtailするコンテナ
var/log/配下のログファイルをtailするコンテナ
アプリケーションのコンテナ。var/log/配下に複数のログファイルを出力
監査ログ
• kube-apiserverの起動オプションとして、監査ログの設定を指定することで、有効になる• --audit-log-path string
• 監査ログの出力先。 ‘-‘ を指定すると標準出力に書き出す
• --audit-log-format• 監査ログのフォーマット
• --audit-log-maxage int• 監査ログを保持しておく期間
• --audit-log-maxbackup• 監査ログを保持しておく最大のファイル数
• --audit-log-maxsize• 監査ログをローテートするまでの最大容量
• --audit-policy-file• 監査ポリシーの設定を記述するファイルのパス。これを指定するとAdvancedAuditingが有効になる
• --audit-webhook-config-file• 外部に監査イベントを送信するWebhook機能の設定ファイルのパス。Webhookは
‘AdvancedAuditingに含まれる機能
• --audit-webhook-mode• Webhookの送信モードを指定するプロパティ
AdvancedAuditingはv1.9時点でBetaだが、着実にエンハンスされている様子
ハンズオン (1)manifestファイルをつかったkubectlの呼び出し方 / ロギングをやってみる
ハンズオンチュートリアルはこちら
•http://bit.ly/cndjp2-handson1
後半戦
後半戦のメニュー
1. 永続化の機能の使い方
2. コンテナのアップデート
3. セキュリティ上の考慮点
永続化の機能の使い方
Volume
• コンテナにマウント可能なボリュームを定義する情報
• ディスクの実態をポイントする
Volumeの定義
保存領域の実態
マウント
YAMLでの記述例
• Podを定義するYAMLの例
apiVersion: v1kind: Podmetadata:
name: counterspec:
containers:- name: countimage: busybox…volumeMounts:- name: varlog
mountPath: /var/log- name: config-volume
mountPath: /etc/counter-configvolumes:- name: varloghostPath:
path: /var/log/counter- name: config-volumeconfigMap:
name: counter-config
コンテナにマウントするVolumeと、マウント先のパスの指定
ボリュームの定義。Volumeの名前と保存領域の実態の指定
PersistentVolume/PersistentVolumeClaim
• PersistentVolumeClaimで必要なディスクの要件を指定すると、それを満たすPersistentVolumeが自動的に選択される
VolumePersistentVolumeClaim
PersistentVolume
YAMLでの記述例
• Podを定義するYAMLの例
apiVersion: apps/v1beta1kind: Podspec:…template:…
spec:containers:- image: sample/mysqlname: mysql…volumeMounts:- name: mysql-persistent-storagemountPath: /var/lib/mysql
volumes:- name: mysql-persistent-storagepersistentVolumeClaim:claimName: mysql-pv-claim
Volumeを指定するところでPersistentVolumeClaimを指定
YAMLの記述例
• PersistentVolume/PersistentVolumeClaimのYAMLの例• この場合Claimの要件をPersistentVolumeを満たすので、選択される候補と
なる
apiVersion: v1kind: PersistentVolumemetadata:name: mysql-hostpath-pv
spec:capacity:storage: 5Gi
accessModes:- ReadWriteOnce
persistentVolumeReclaimPolicy: RetainhostPath:path: /data/mysql
apiVersion: v1kind: PersistentVolumeClaimmetadata:name: mysql-pv-claim
spec:accessModes:- ReadWriteOnce
resources:requests:storage: 5Gi
Volumeのいろいろな使い方
• 通常のディスクとして使う以外に、Containerに設定情報などを受け渡す手段としても使われる(詳細は後述)• secret, downwardAPI, ConfigMap
• コンテナからはKey/Valueが記述されたファイルや、環境変数として、これらの情報を参照できる
Volume定義として設定情報を記述
Volumeの種類(一部)
• 一般的なデータの保持に利用するもの
• 設定情報等の受け渡し用• secrets
• downwardAPI
• configMap
• Kubernetesでは様々なディスクボリュームをサポート
• お試し用?• hostPath
• emptyDir
• 本番用• awsElastic
BlockStore
• cephfs
• nfs
• iscsi
…
• その他• flocker
• gitRepo
…
hostPath
• Podが稼働するホストのファイル/ディレクトリをコンテナにマウントして利用する方式
• ストレージ領域を別で用意する必要がなく、比較的手軽に利用できるので、デモ用途等に向く
• 他に、ホストOSのファイルシステムにアクセスする必要があるときにも利用する• e.g. cAdvisorを使っているとき
hostPath利用時の注意点
• Volumeの設定が同じPodでも、マウントされるNode異なれば、マウントされるファイルの内容が違う(稼働しているホストのファイルシステムがマウントされるため)
→特にPodをスケールアウトさせると危険
• 書き込みをするには、コンテナをroot権限で実行する(privileged container)か、マウントされる領域に対して書込み権限を与える必要がある
awsElasticBlockStore
• AWSのEBSを利用する方式
• AWS EC2でPodを稼働させているときしか使えない
• 同じEBSをマウントできるPodは一つだけ
• EC2インスタンスとEBSが同一リージョン、同一AZに配置される必要がある
iscsi/nfs
• iscsi• iSCSIボリュームをマウントする方式
• nfs• NFS(Network File System)ボリュームをマウントする方式
downwardAPI
• コンテナ内のアプリケーションが、自分自身が稼働する環境(Container, Pod, Node)の情報を取得するために使う
• この例では、• /etc/labelsからlabelのキー/値
• /etc/annotationsからannotationのキー/値を取得できる
apiVersion: v1kind: Podmetadata:name: downwardapi-volume-examplelabels:…
annotations:…
spec:containers:
…volumeMounts:- name: podinfomountPath: /etcreadOnly: false
volumes:- name: podinfodownwardAPI:items:- path: "labels"fieldRef:fieldPath: meta.labels
- path: "annotations"fieldRef:fieldPath: meta.annotations
downwardAPI
• 取得できる値(v1.8時点)• Node名
• NodeのIP
• Pod名
• Podのnamespace
• PodのIP address
• Podのservice account名
• PodのUID
• ContainerのCPU limit
• ContainerのCPU request
• Containerのmemory limit
• Containerのmemory request
• Podに設定されたlabel
• Podに設定されたannotation
configMap
• 一般的な設定情報を受け渡すために使う…。
• この例では、• /etc/config/example.prop.1
というファイルに値”hello”が入る
• /etc/config/example.prop.1というファイルに値”world”が入る
apiVersion: v1kind: ConfigMapmetadata:name: example-config
data:example.prop.1: helloexample.prop.2: world
---apiVersion: v1kind: Podmetadata:name: pod-using-config
spec:containers:- name: example-container
volumeMounts:- name: config-volumemountPath: /etc/config
volumes:- name: config-volumeconfigMap:name: example-config
secrets
• 機密度の高い情報を保持する際に使うVolume• DBなどの接続情報• クララスター内/外のサービスのアクセストーク
ン• SSL/TLSの証明書…
• コンテナで利用するときはメモリ内に保持され、不要になったら削除される(tmpfsが使われている)
• ファイルの実態はマスターノード(etcd)に保持される
etcd
secrets利用時の注意点
• etcdに平文で保持されるので、ここをしっかり守る• etcdのデータを正しく管理する
• アクセス権制御を行う
• 秘密情報を書き込んだsecretsオブジェクトのYAML/JSON定義を、ソースコードリポジトリに入れない
• アプリケーションが秘密情報を取得したら、それを正しく扱うよう実装すること(Kubernetesのレイヤーでは何もできない)
Volumeの種類は他にも沢山…。
• ドキュメントに目を通すと良い。
• https://kubernetes.io/docs/concepts/storage/volumes/
PersistentVolumeの動的プロビジョニング
• PVC内でStorageClassを指定。StorageClassは性能やサービスレベルに対応付けて作成するオブジェクト
• PVCが作られると、StorageClassで設定されたプロビジョナーがVolumeを確保しにいく
VolumePersistentVolumeClaim
StorageClass
Provisioner
YAMLの記述例
• Storageの速度の違いで名前を分けた場合の例(Google Compute Engineのサービスの種類を対応付けている)
• provisionerがGCE上にストレージを確保する操作を行う
• parametersはprovisioner固有の設定値
• reclaimPoliciyで解放後にVolumeを削除するか、残すかを指定(Delete/Retain)
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata:
name: slowprovisioner: kubernetes.io/gce-pdreclaimPolicy: Retainparameters:
type: pd-standard
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata:
name: fastprovisioner: kubernetes.io/gce-pdreclaimPolicy: Retainparameters:
type: pd-ssd
YAMLの記述例
• PersistentVolumeClaimでStorageClass: fastを指定→ 対応するStorageClassに書かれたprovisionerとパラメータ
でボリュームを確保
apiVersion: v1kind: PersistentVolumeClaimmetadata:name: claim1
spec:accessModes:- ReadWriteOnce
storageClassName: fastresources:requests:
storage: 30Gi
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata:name: fast
provisioner: kubernetes.io/gce-pdreclaimPolicy: Retainparameters:type: pd-ssd
コンテナのアップデート
ローリングアップデート
• Deploymentオブジェクトを使ってコンテナを展開しておくと、ReplicaSetが自動的にアップデート管理してくれるようになる
• コンテナイメージの変更(例えばv1 -> v2に差し替え)を支持すると、自動的にローリングアップデートが行われる
> kubectl set image deployments/[Deployment名] [イメージ名]
カナリーデプロイメント
• Label, LabelSelectorをうまく使うことで実現する。まずは初期状態…
labels: tier: frontapp: guestbooktrack: stable
Image: guestbook:v1
D
カナリーデプロイメント
• tierとappのLabelの値でルーティング対象となるようにServiceにLabelSelectorを設定
tier = frontapp = guestbook
クラスター外からのリクエスト
D
Service
labels: tier: frontapp: guestbooktrack: stable
Image: guestbook:v1
カナリーデプロイメント
• カナリーとして新バージョンのコンテナを追加する際、Serviceのルーティング対象となるようにlabelを設定してDeploymentを作成
Service
tier = frontapp = guestbook
クラスター外からのリクエスト
DD labels:
tier: frontapp: guestbooktrack: stable
Image: guestbook:v1
labels: tier: frontapp: guestbooktrack: canary
Image: guestbook:v2
カナリーデプロイメント
• 最終的に、安定版(この例ではtrack=stable)のイメージを、新バージョンに変更する
tier = frontapp = guestbook
クラスター外からのリクエスト
D
Service
labels: tier: frontapp: guestbooktrack: stable
Image: guestbook:v2
セキュリティ上の考慮点
セキュリティ上の考慮点 – クラスターレベル
• 外部とやりとりするところの…
apiserver API呼び出しSSHアクセス
>_
コンテナレジストリアプリケーションへリクエスト
kubelet API呼び出し
コンテナ取得
セキュリティ上の考慮点 – クラスターレベル
• それぞれで対策を講じる
apiserver API呼び出しSSHアクセス
>_
コンテナレジストリアプリケーションへリクエスト
kubelet API呼び出し
コンテナ取得 APIの認証/認可機能を利用する
NodeへのSSHアクセスを制限する
コンテナレジストリのクレデンシャルを保護する
APIの認証/認可機能を利用する
apiserverのAPIの認証/認可機能を利用する• 認証方式として選択できるもの
• X.509証明書
• 固定のトークン
• LDAP連携
• OpenID Connect
…
• 要件に応じて適したものを選ぶ…。
apiserverのAPIの認証/認可機能を利用する• 以下の情報を使って制限をかけられる模様
• ユーザー• グループ• 認証時に設定したキー/値• API Resourceに対する操作か否か• リクエストのパス• APIリクエストの種類(get, list, create…)• HTTPリクエストの種類(GET, POST…)• 操作しようとしているリソース/そのサブリソース• Namespace• APIグループ
• すいません詳細は勉強します• https://v1-8.docs.kubernetes.io/docs/admin/authorization/
kubelet APIの認証/認可機能を利用する
• kubelet APIはクラスター内部で使われるInternalなもの
• kubeletのAPIはデフォルトで匿名アクセスを許可する設定になっているので、これを無効にする• kubeletの起動時に--anonymous-auth=falseを設定
• 認可もデフォルトでは全て許可(認証に成功すればどの操作もできる)されている。以下の設定でapiserverのAPIのポリシーを適用するように変更• apiserverでauthorization.k8s.io/v1beta1のAPIグループを有効化• 以下のフラグを設定してkubeletを起動
• --authorization-mode=Webhook, --kubeconfig, --require-kubeconfig
NodeへのSSHをアクセスを制限する
• NodeにSSH等で直接アクセスを行うと、Kubernetesの認証/認可機構を無視して操作できてしまう。
• NodeのOSに直接アクセスする手段は、必要以上に利用せず、“kubectl exec”コマンドで代替する。
> kubectl exec [Podの名前] [コマンド]
コンテナレジストリのクレデンシャルを安全に保持する• コンテナレジストリへのアクセス情報を保持するSecretを作成
し、Podでそれを利用するように設定する
apiVersion: v1kind: Podmetadata:
name: private-regspec:
containers:- name: private-reg-containerimage: <your-private-image>
imagePullSecrets:- name: <secret-name>imagePullsecretsでSecretを指定
コンテナレジストリのクレデンシャルを安全に保持する• Secretの作り方
• このSecretには、docker login を実行したときに作られるDockerレジストリのアクセストークンと同じデータが含まれる
> kubectl create secret docker-registry <secret-name> \--docker-server=<your-registry-server> \--docker-username=<your-name> \--docker-password=<your-password> \--docker-email=<your-email>
セキュリティ上の考慮点 – コンテナレベル
• コンテナ自体の安全性を確保する• 信頼できる/メンテできるコンテナを利
用する• コンテナ内のSWの脆弱性対策をおこな
う
• コンテナが悪さをしたときに影響を最小限にする• 利用リソースを制限する• ネットワークアクセスを制限する• 実行権限を調整する• 稼働するノードを制限する
信頼できる/メンテできるコンテナを利用する• イメージの生い立ち
• 誰が、いつ、どうやって作ったイメージか• 信頼できる配布元が作成したものか• メンテナンスが継続的に行われているか
• 不必要なパッケージが少ないこと• 不必要なパッケージが少ないほど潜在的な注意を払う対象が減る
• 脆弱性の発見しやすさ• 脆弱性があることを検知できるか• 脆弱性対応状況が公開されているか
• サポート• セキュリティパッチはどのくらいの期間提供されるか
コンテナ内のSWの脆弱性対策をおこなう
• 脆弱性の継続的な調査
• コンテナにセキュリティパッチを適用
=コンテナに対しても、当たり前のことをちゃんとやるCIツールも充実してきているので、うまく活用しましょう
コンテナの利用リソースを制限する
• Resource quotaを設定して大量のリソースを専有してしまうことを防止する
• Resource quotaはNamespace単位で設定するのが基本• Namespaceはクラスター内のオブジェクト群をくくる単位
(e.g. 開発者ごとにNamespaceを割り当ててクラスターを共有するなど)
• Namespaceの作り方
> kubectl create namespace mem-limited-example
コンテナの利用リソースを制限する
• Resource quotaのYAML定義• メモリ量を制限する例 apiVersion: v1
kind: LimitRangemetadata:
name: mem-limit-rangespec:
limits:- default:
memory: 512MidefaultRequest:
memory: 256Mitype: Container
このquotaが設定されたNamespaceのコンテナは、デフォルトで256M割り当てられ、512Mが上限となる
コンテナのネットワークアクセスを制限する• NetworkPolicyでPod間のアク
セスポリシーを定義するkind: NetworkPolicyapiVersion: networking.k8s.io/v1metadata:
name: access-nginxspec:
podSelector:matchLabels:
run: nginxingress:- from:- podSelector:
matchLabels:access: "true"
ポリシーを適用するPodを特定するLabel
access: “true”が設定されたオブジェクトからのアクセスのみ受け付ける
コンテナ実行時の権限を調整する
• SecurityContextを設定して、コンテナの実行ユーザーを指定する
apiVersion: v1kind: Podmetadata:
name: security-context-demo-2spec:
securityContext:runAsUser: 1000
containers:- name: sec-ctx-demo-2image: gcr.io/google-samples/node-hello:1.0securityContext:
runAsUser: 2000allowPrivilegeEscalation: false
このPod内のコンテナはUID 1000のユーザーで実行
コンテナ毎に設定するとPod単位の設定をオーバーライドする
コンテナが稼働するノードを制限する
• NodeSelectorをPodに設定
• 所定のLabelが設定されたNodeにのみデプロイされる
apiVersion: v1kind: Podmetadata:
name: nginxlabels:env: test
spec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresent
nodeSelector:disktype: ssdこのPodは、disktype: ssdが設定さ
れたNodeにのみデプロイされる
その他のセキュリティ対策
• etcdのバックアップを暗号化する
• 各種クレデンシャルを安全に保持する(secretsを利用する)
etcd
その他のセキュリティ対策
• 各種ログをちゃんと取る(やりかたは前述)
• 監査ログを有効にする
• 各ノードのログを取得する
ハンズオン (2)アプリケーションを動かしてみよう!
ハンズオンチュートリアルはこちら
•http://bit.ly/cndjp2-handson2
次回予告
次回コンテンツ
• 「Kubernetes Network Deep Dive!」
• コンテンツ• 今回取り上げられなかった、k8sネットワーク周りを深掘り
• サービス・メッシュでk8s上にインテリジェントなネットワークを
お疲れ様でした!#cndjp1
top related