😽

helmパッケージ化されたアプリをKubernetes+Istioを使って公開する

2018/09/11に公開

Istio+helm
これまで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"

起動するとターミナルは下記のような状態になります。

docker runの実行結果

この状態でブラウザで http://localhost:5678 にアクセスすると、起動時に指定したhello worldが表示されてているはずです。

ブラウザでの表示結果

docker runで動かしたコンテナを停止する場合はCtrl+Cを使用します。

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.yamlvalues.yamltemplates/deployment.yamltemplates/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