helmパッケージ化されたアプリをKubernetes+Istioを使って公開する
これまでkubernetes上でアプリを動かす時に基本的にhelmにまとめてデプロイしてきましたが、upgradeするたびに瞬断する問題の解決と、カナリアリリースを利用したブルーグリーンデプロイメントを実現するために、既存のhelmを使ったワークロードにIstioを絡めて利用する方法を書いていきます。
IstioはKubernetes上に展開したマイクロサービスの接続をマネージメントしてくれるコンポーネントで、簡単に言うとIngressの高機能版です。
環境
今回のKubernetes環境としてはDocker for Mac with Kubernetesで動きを見ていきます。
アプリは、hashicorp/http-echo を使って構築していきます。これは簡単なWebアプリケーションで、コンテナの起動引数を使ってレスポンスボディを指定できるものになります。
まずはイメージの動作確認を兼ねてdockerコマンドでコンテナを作成・起動してみます。
実行方法はUSAGEの通りです。
docker run -p 5678:5678 hashicorp/http-echo -text="hello world"
起動するとターミナルは下記のような状態になります。
この状態でブラウザで http://localhost:5678 にアクセスすると、起動時に指定したhello world
が表示されてているはずです。
docker runで動かしたコンテナを停止する場合はCtrl+C
を使用します。
helmパッケージの作成とデプロイ
次にこのイメージをkubernetes上に展開するためにhelm chartを作成して、gitのバージョン管理配下に置きます。
helm create sample
cd sample/
git init
git add .
git commit -m 'first commit'
作成したhelmパッケージに対し、先ほどdockerコマンドで立ち上げたようにhashicorp/http-echoを立ち上げる設定をします。編集するファイルはChart.yaml
、values.yaml
、templates/deployment.yaml
、templates/NOTES.txt
の4つです。
vi Chart.yaml
vi values.yaml
vi templates/deployment.yaml
vi templates/NOTES.txt
編集内容は下記の通りです。
git diff
編集が完了したらコミットし、タグを付けます。
git commit -a -m "bump version to 1.0.0"
git tag 1.0.0
作成したhelmパッケージをインストールしていきます。今回は説明の都合上、release nameをfoolish-penguin
に固定します。
helm install --name=foolish-penguin .
表示されたNOTESを元にポートフォワーディングを設定してインストールされたpodにアクセスできるかどうか確認します。
ブラウザで http://localhost:5678 にアクセスし、"hello world v1"
と表示されればOKです。
このポートフォワーディングもdocker run同様Ctrl+C
で終了することができます。
ちなみに今回はDeploymentを作成しているので、Deploymentに対してポートフォワーディングを設定することもできます。
kubectl port-forward deployment/foolish-penguin-sample 8081:5678
Istioを利用する場合はServiceに対してルーティングすることになるので、Serviceへもポートフォワーディングを設定して動作を確認しておきます。
kubectl port-forward svc/foolish-penguin-sample 8082:80
一通り確認し終わったらCtrl+Cで終了し、1つ上のディレクトリまで戻ります。
cd ..
Istioのダウンロードとhelmを使ったインストール
次にIstioの最新版をダウンロードし、ローカルに作成されだディレクトリの中へ移動します。
この記事をまとめている時点では1.0.1が最新になっています。
(参考:https://istio.io/docs/setup/kubernetes/download-release/ )
curl -L https://git.io/getLatestIstio | sh -
cd istio-*/
helmを実行するためのサービスアカウントをcluster-adminにアップデートし、Istioのインストールを行います。
kubectl apply -f install/kubernetes/helm/helm-service-account.yaml
helm init --service-account tiller --upgrade
helm install install/kubernetes/helm/istio --name istio --namespace istio-system
Istioを構成する様々なリソースがインストールされます。インストールされたリソースは下記のコマンドで確認することができます。
kubectl -n istio-system get all
インストールが完了したら1つ上のディレクトリまで戻ります。
cd ..
helmパッケージのIstio対応
ベースとなるhelmパッケージを作成し、同様にGitの管理下に置きます。
helm create sample-gateway
cd sample-gateway/
git init
git add .
git commit -a -m 'first commit'
その後不要なファイルを削除し、IstioのGatewayとVirtualServiceを作成します。
この時、VirtualServiceの destination -> host の値を上記で作成したサービスの名前にするのがポイントです。
rm -f templates/*.yaml templates/NOTES.txt
cat << 'EOF' > values.yaml
nameOverride: ""
fullnameOverride: ""
istio:
hosts:
- 127.0.0.1.xip.io
EOF
cat << 'EOF' > templates/gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: {{ include "sample-gateway.fullname" . }}
labels:
app: {{ include "sample-gateway.name" . }}
chart: {{ include "sample-gateway.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
{{- range .Values.istio.hosts }}
- {{ . | quote }}
{{- end }}
EOF
cat << 'EOF' > templates/virtualservice.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: {{ include "sample-gateway.fullname" . }}
labels:
app: {{ include "sample-gateway.name" . }}
chart: {{ include "sample-gateway.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
hosts:
{{- range .Values.istio.hosts }}
- {{ . | quote }}
{{- end }}
gateways:
- {{ include "sample-gateway.fullname" . }}
http:
- route:
- destination:
host: foolish-penguin-sample
EOF
そしてChart.yamlを編集し、変更内容のコミットとタグ打ちをします。
vi Chart.yaml
git diff Chart.yaml
git add .
git commit -a -m "bump version to 0.1.0"
git tag 0.1.0
helmコマンドを使ってデプロイします。今回も説明の都合上、リリース名をexciting-lemur
に固定します。
helm install --name=exciting-lemur .
Istioの自動注入機能を有効にするため、istio-injectionをdefaultネームスーペースに対して有効にする
kubectl get namespace -L istio-injection
kubectl label namespace default istio-injection=enabled
kubectl get namespace -L istio-injection
既存のhelmパッケージをIstioで利用するためには上記の注入機能を有効にした上でデプロイする必要があります。アップデートついでにレスポンスボディも変えておきます。
cd ../sample
vi Chart.yaml
vi templates/deployment.yaml
git diff
git commit -a -m "bump version to 1.0.1"
git tag 1.0.1
更新したパッケージをデプロイします。
helm upgrade foolish-penguin .
ブラウザで http://127.0.0.1.xip.io:80 を開き、更新されたサービスにistio経由で表示されていることを確認します。この時先ほどのアップデートが適用されていることをレスポンスボディを使って判断します。
アプリケーションのバージョンアップとカナリアリリース
本来はイメージのタグを変えるが今回はスキップしてレスポンスボディの変更で代用します。
vi Chart.yaml
git diff
git commit -a -m "bump version to 1.1.0"
git tag 1.1.0
新しいバージョンのアプリケーションをデプロイします。
この時新しいリリース名をつけてインストールします。
今回も説明の都合上、リリース名をpeeking-rabbit
に固定します。
helm install --name=peeking-rabbit .
もちろんこの時点で http://127.0.0.1.xip.io:80 に変化はありません。
新しいバージョンのServiceに対してポートフォワーディングを設定し、デプロイできているか確認して見ます。
kubectl port-forward svc/peeking-rabbit-sample 8083:80
ブラウザで http://localhost:8083 にアクセスし、hello world peeking-rabbit
と表示されていれば成功です。
一通り確認し終わったらCtrl+Cで終了し、sample-gatewayのディレクトリまで戻ります。
cd ../sample-gateway
新しいバージョンにリクエストの半分を割り当てるよう設定を追加し、バージョンを上げます。
vi Chart.yaml
vi templates/virtualservice.yaml
git diff
git commit -a -m "bump version to 0.1.1"
git tag 0.1.1
Istioの設定を更新するためにhelmコマンドでデプロイします。
helm upgrade exciting-lemur .
その後ブラウザで http://127.0.0.1.xip.io:80 に何度かアクセスし、表示されているページが変化することを確認できたら完了です。
試しにcurlでHTTPリクエストを10回実行すると、ほぼ指定したウェイト通りに分配されていることが確認できます。
for i in `seq 0 9` ; do curl 127.0.0.1.xip.io ; done
以上でhelmパッケージのIstio対応とカナリアリリースの設定が完了しました。
Discussion