Kubernetes とはどのようなものかステップバイステップで実際に手を動かしながら見ていきます。
このハンズオンでは Kubernetes の最小単位である Pod から見ていき、最終的に Deployment と LoadBalancer Service を使ったアプリケーションのデプロイを体験します。
また、Kubernetes クラスター上のノードを起動している間お金がかかり続けますので、最後の「後片付け」のステップは必ず実行してください。
- ブラウザから手順書(このリポジトリ)を開く
https://git.io/fjCRU - Azure ポータルを開く
https://portal.azure.com/ - Azure Cloud Shell を開く(Bash を選択)
- Azure Cloud Shell でサンプルリポジトリをクローンする
git clone https://github.com/softoika/decode2019-k8s-handson
サンプルリポジトリへ移動
cd decode2019-k8s-handson
リソースグループを作成する
az group create --name decode2019-cd65-71 --location japaneast
リソースグループ上に Kubernetes クラスターを作成する
az aks create --resource-group decode2019-cd65-71 --name k8s-handson --node-count 1 --generate-ssh-keys
作成にはしばらく時間がかかる。以下のコマンドでステータスがSucceeded
になるまで待つ (Ctrl+C で終了)
watch "az aks show -g decode2019-cd65-71 -n k8s-handson | grep provisioningState"
Kubernetes クラスターに接続するための認証情報を取得する
az aks get-credentials --name k8s-handson --resource-group decode2019-cd65-71
Pod は Kubernetes における最小単位の環境です。
Pod は 1 つ以上のコンテナを動かす環境で、複数のコンテナを動かす場合同じ Pod 内であれば コンテナは localhost で互いに通信することができます。
Pod のマニフェストファイルの単純な例は以下の通りです。
pod-example.yaml
# /api/v1/namespaces/{namespace}/pods にリクエストを投げる
apiVersion: v1
kind: Pod
metadata:
name: pod-example
spec:
containers:
- name: hello-app-container
# コンテナイメージを指定
image: rhanafusa/hello-app:1.0
マニフェストファイルの適用はkubectl apply
コマンドを使います。
kubectl apply -f pod-example.yaml
また、kubectl get
コマンドで Pod の起動状態を確認できます。
kubectl get pods
STATUS が Running になったら起動成功
# yamlに何を記述できるかコマンドで確認する
kubectl explain pod
kubectl explain pod.spec
kubectl explain pod.spec.containers.ports
# podの詳細や起動履歴を確認する
kubectl describe pods
# アプリケーションのログを確認する
kubectl logs pod-example
# podの中に入る(pod内で有効なコマンドを実行する)
kubectl exec -it pod-example -- bash
kubectl exec -it pod-example -- uname -a
その他コマンドの詳細を知りたければkubectl -h
またはkubectl サブコマンド -h
でみれます。
また、公式でコマンドのリファレンスが公開されています。
ReplicaSet はその名の通り、Pod のレプリケーションを組んで可用性を高めることができます。
以下は 3 つのレプリカで構成された ReplicaSet の例です。
replicaset-example.yaml
# /apis/apps/v1/namespaces/{namespace}/replicasets にリクエストを投げる
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-example
spec:
replicas: 3
selector:
# labelの検索条件
matchLabels:
app: hello-app
template:
# template以下がPodとほとんど同じ
metadata:
labels:
app: hello-app
spec:
containers:
- name: hello-app-container
image: rhanafusa/hello-app:1.0
適用
kubectl apply -f replicaset-example.yaml
レプリカ数3台でReplicaSetが起動されていることを確認
kubectl get replicaset -o wide
Pod それぞれがハッシュ付きの名前で異なる IP アドレスで起動されている
kubectl get pods -o wide
ReplicaSet を組んでいれば Pod に障害が起きて停止しても、すぐに Pod が再作成されていることがわかる。
以下のシェルスクリプトを実行すると、Pod の削除前と削除後で Pod の数が変わっていないことがわかる。
./self-healing-demo.sh
Deployment は ReplicaSet をスケーラブルに扱うためのリソース。
simple-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: simple-deployment
spec:
replicas: 3
selector:
matchLabels:
app: hello-app
template:
metadata:
labels:
app: hello-app
spec:
containers:
- name: hello-app-container
image: rhanafusa/hello-app:1.0
Deployment はアプリケーションを更新するときに、後述のローリングアップデートやオートスケーリングなどのデプロイに関する設定を記述することができる。
よって、基本的には Pod や ReplicaSet は Deployment を通して定義すればよいです(Deployment のマニフェストファイルだけ作れば OK)。
Deployment では基本的にローリングアップデートでアプリケーションが順次更新されるため、ダウンタイムなしにアプリケーションを更新することができます。 ローリングアップデートのデモ用マニフェストは以下の通りです。
rolling-update-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: rolling-update-deployment
spec:
## ローリングアップデートの設定 ##
# 新規作成されたPodがReadyになってから起動成功と判断するまでの猶予時間
minReadySeconds: 3
strategy:
type: RollingUpdate
rollingUpdate:
# 1台ずつ更新していく
maxSurge: 1
maxUnavailable: 0
##############################
replicas: 3
selector:
matchLabels:
app: hello-app
template:
metadata:
labels:
app: hello-app
spec:
containers:
- name: hello-app-container
image: rhanafusa/hello-app:1.0
それではローリングアップデートを体験してみましょう。
以下のシェルスクリプトを実行してローリングアップデートされていく様子を確認することができます。
./rolling-update-demo.sh
Ctrl + C
でスクリプトを終了できます。
シェルスクリプトの内容を一部抜粋すると以下のようになっています。
# Deploymentを作成
kubectl apply -f rolling-update-deployment.yaml
# コンテナイメージを変更
kubectl set image deployment rolling-update-deployment hello-app-container=rhanafusa/hello-app:1.1
# 新しいReplicaSetが作成されて順次Podが更新されていることを確認
watch kubectl get replicaset
レプリカの数は手動で変更することもできますが、以下のようにマニフェストを設定することで Pod の負荷状況に応じて自動でスケールアウトすることができます。
autoscale-example.yaml
## HorizontalAutoscalerの設定
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: autoscale-example
spec:
# レプリカ数の下限
minReplicas: 2
# レプリカ数の上限
maxReplicas: 5
# PodのCPUが70%になるように調節する
targetCPUUtilizationPercentage: 70
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: autoscalable-deployment
---
## 対象のDeploymentの設定
apiVersion: apps/v1
kind: Deployment
metadata:
name: autoscalable-deployment
spec:
selector:
matchLabels:
app: hello-app
template:
metadata:
labels:
app: hello-app
spec:
containers:
- name: hello-app-container
image: rhanafusa/hello-app:1.0
Kubernetes 上のアプリケーションを外部に公開するには Service (もしくは Ingress) というリソースを使います。
以下は負荷分散のためのシンプルなロードバランサーの Service の例です。
service-example.yaml
## シンプルなServiceの定義
apiVersion: v1
kind: Service
metadata:
name: service-example
spec:
type: LoadBalancer
ports:
- protocol: "TCP"
# 8080番ポートに受けて各Podの8080番ポートに転送する
port: 8080
targetPort: 8080
selector:
# Deploymentと同じラベルをつける
app: hello-app
---
## Serviceに対応したDeploymentを定義
apiVersion: apps/v1
kind: Deployment
metadata:
name: service-example-deployment
spec:
replicas: 3
selector:
matchLabels:
app: hello-app
template:
metadata:
labels:
app: hello-app
spec:
containers:
- name: hello-app-container
image: rhanafusa/hello-app:1.0
# コンテナのポートを指定
ports:
- containerPort: 8080
適用
kubectl apply -f service-example.yaml
Service の EXTERNAL-IP がから特定の IP アドレスになるまで待ちます(Ctrl + C
で終了)
kubectl get services --watch
EXTERNAL-IP が実 IP になったら、ブラウザでアクセスしてみましょう。(http://<EXTERNAL-IP>:8080/greeting
でアクセスできます。)
従量課金の場合、ノードが起動している間はお金がかかり続けます。
以下のコマンドを実行して(もしくは Azure Portal の画面上から)、このハンズオンのリソースグループごと消してしまいましょう。
az group delete --name decode2019-cd65-71 --yes --no-wait
今回 Azure Cloud Shell を初めて使った場合 Cloud Shell 用のストレージとリソースグループも作成されています。
僅かではありますが、起動している間お金がかかります。
こちらも普段使っていないのであれば削除しておきましょう。
az group delete --name cloud-shell-storage-southeastasia --yes --no-wait