前回までで以下のようなリソースについて紹介しました。
今回はこれらの知識を使って、簡単なウェブサービスをパブリッククラウドで公開してみたいと思います。
Kubernetesをパブリッククラウドで利用する場合、各社のマネージドサービスを利用することができます。代表的なKubernetesのマネージドサービスは、
- GKE (Google)
- EKS (AWS)
- AKS (Azure)
- OKE (OCI)
などがあります。
今回はOracleのOKEを使って、自作のサービスをインターネットに公開してみます。なお、前回までで紹介した知識だけで公開するので、本番想定ではない点については注意してください。あくまで各コンポーネントの動きを理解する目的です。
OKEクラスターを作成する
OKEのクラスターを作成して、ターミナルからkubectl
コマンドが利用できるようにします。
OKEクラスターのプロビジョニング
OCIのホーム画面に移動したら、右上のハンバーガーメニューから、「開発者サービス」->「 Kubernetesクラスタ(OKE)」を選択します。
「クイック作成」が選択されていることを確認して、「送信」を選択します。
ここ以降は、すべてデフォルトのまま次に進みます(もしサービス制限の関係でインスタンスが3つ用意できない場合、ノード数を減らしてください)。
以下のようにマークが緑色になったらプロビジョニング完了です。
アクセス確認
kubectl
をインストールしている端末から、アクセス確認を行います。
「ローカル・アクセス」を選択し、表示される手順に従います。なお、エンドポイントは「パブリックエンドポイント」の方で操作を行います。
kubectl get nodes
コマンドを実行して、正しくノードの情報がとれていれば成功です。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
10.0.10.122 Ready node 19m v1.29.1-6+b511b8ca8a18c5
10.0.10.42 Ready node 19m v1.29.1-6+b511b8ca8a18c5
10.0.10.55 Ready node 19m v1.29.1-6+b511b8ca8a18c5
コンテナイメージのリモートレポジトリを作成する
自作のアプリケーションをKubernetesクラスターで動かす場合、以下のようなイメージでコンテナイメージをやり取りします。
- 作成したアプリケーションのコンテナイメージをリモートレポジトリ(この場合はOCIR)にプッシュ
- アプリケーションをデプロイするためのマニフェストファイルをクラスターに適用(マニフェストファイルにはイメージをプッシュしたレポジトリの情報が記載されている)
- クラスターは、マニフェストファイルを適用するうえで、レポジトリからイメージをプルしてくる
このような動作になるため、リモートレポジトリを作成する必要があります。OCIでは、OCIRというサービスがあるのでそれを利用します。
レポジトリを作成
OCIのコンソールに移動し、左上のハンバーガーメニューから、「開発者サービス」、「コンテナ・レジストリ」を選択します。
まず、ウェブサーバのイメージをプッシュするリポジトリを作成します。
ご自身のコンパートメントが選択されているかを確認します。アクセスは「パブリック」にし、リポジトリ名はお好きな値を入力します。私は4qiita_sample/web
としました。入力が完了したら「作成」を選択します。
次に、DBのイメージをプッシュするリポジトリを作成します。
同様の手順で、名前を4qiita_sample/db
として作成します。
以上でコンテナイメージのリモートレポジトリの作成は完了です。
OCIRについて
OCIRは一般的なコンテナレジストリと少し仕様が異なるのでここで説明しておきたいと思います。
一般的なコンテナレジストリでは、レポジトリを作成し、その中で複数目的のイメージを配置することができると思います(例えば以下のような構成)。
└── 4qiita-sample
├── db
│ ├── 1.1
│ ├── 1.2
│ └── latest
└── web
├── 1.1
├── 1.2
└── latest
OCIRでは、このように同一レポジトリ内に複数の目的のイメージを配置することができません。もう少し正確に言うと、リポジトリ内はディレクトリのような構造を取ることができません(同一リポジトリ内のイメージはタグでしか区別することができない)。
そのため、OCIRで複数イメージを使ったサービスを管理する場合、以下のように構成する必要があります。
├── 4qiita-sample/db (リポジトリ1)
| ├── 1.1
| ├── 1.2
| └── latest
└── 4qiita-sample/web(リポジトリ2)
├── 1.1
├── 1.2
└── latest
このような仕様のため、上記手順では2つのリポジトリ(web用とdb用)を作成しました。
レポジトリアクセスのために認証トークンを取得
以前の記事でも説明しましたが、レポジトリアクセスにはOCIのユーザー名と認証トークンを利用しますので、取得してメモなどに控えておいてください。
レポジトリにログイン
docker login
コマンドでログインしてください。詳細は以前の記事で確認してください。
アプリケーションのイメージをOCIRにプッシュ
それでは、アプリケーションイメージをOCIRにプッシュしたいと思います。
まず、今回使用するアプリケーションのソースコードをダウンロードします。
$ git clone git@github.com:sogawa-yk/simple-knowledge-sharing-platform.git
$ cd simple-knowledge-sharing-platform
$ git checkout tags/9-article -b 17-article-branch
webサーバのイメージをプッシュ
以下の手順でビルド・プッシュを行います。
なお、<region-code>
はご自身が作成したOCIRのリージョンコードをここのリージョンキーをみて調べてください。また、リージョンキーは小文字で入力します。
<tenancy-namespace>
は、OCIコンソール画面の右上のプロファイルアイコンをクリックし、「テナンシ」を選択、遷移した画面にある「オブジェクト・ストレージ・ネームスペース」の値を入力します。
$ cd web # webサーバ用のディレクトリに移動
$ docker build -t simple-knowledge-sharing-platform/web .
$ docker tag simple-knowledge-sharing-platform/web:latest <region-code>.ocir.io/<tenancy-namespace>/4qiita-sample/web:latest
$ docker push <region-code>.ocir.io/<tenancy-namespace>/4qiita-sample/web:latest
dbのイメージをプッシュ
以下の手順でビルド・プッシュを行います。
$ cd ../db # db用のディレクトリに移動
$ docker build -t simple-knowledge-sharing-platform/db .
$ docker tag simple-knowledge-sharing-platform/db:latest <region-code>.ocir.io/<tenancy-namespace>/4qiita-sample/db:latest
$ docker push <region-code>.ocir.io/<tenancy-namespace>4qiita-sample/db:latset
以上でリモートレポジトリへのプッシュは完了です。
マニフェストファイルの作成
次に、クラスターにデプロイするために各リソースのマニフェストファイルを作成します。今回作成するリソースは、
- WebサーバのDeployment
- DBのDeployment
- Webサーバアクセス用のService
- WebサーバがDBにアクセスするためのService
の4つです。
WebサーバのDeployment
適当なディレクトリに移動して、以下のコマンドでまずマニフェストファイルのひな型を作成します。
$ kubectl create deploy 4qiita-sample-web --image=<region-code>.ocir.io/<tenancy-namespace>/4qiita-sample/web:latest --replicas=3 --dry-run=client -o yaml >> deploy_web.yaml
以下のようなyamlが出力されるはずです。
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: 4qiita-sample-web
name: 4qiita-sample-web
spec:
replicas: 3
selector:
matchLabels:
app: 4qiita-sample-web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: 4qiita-sample-web
spec:
containers:
- image: <imageで指定した値>
name: web
resources: {}
status: {}
このままでも問題ありませんが、不要な部分を削除にしてシンプルにします。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: 4qiita-sample-web
name: 4qiita-sample-web
spec:
replicas: 3
selector:
matchLabels:
app: 4qiita-sample-web
template:
metadata:
labels:
app: 4qiita-sample-web
spec:
containers:
- image: <imageで指定した値>
name: web
DBのDeployment
同様に、DBもまずひな型を作成します。
$ kubectl create deploy 4qiita-sample-db --image=<region-code>.ocir.io/<tenancy-namespace>/4qiita-sample/db:latest --replicas=1 --dry-run=client -o yaml >> deploy_db.yaml
修正すると以下のようになります。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: 4qiita-sample-db
name: 4qiita-sample-db
spec:
replicas: 1
selector:
matchLabels:
app: 4qiita-sample-db
template:
metadata:
labels:
app: 4qiita-sample-db
spec:
containers:
- image: <imageで指定した値>
name: db
Webサーバアクセス用のService
同様に、以下のコマンドでひな型を作成します。
$ kubectl create svc loadbalancer qiita-sample-web --tcp=8080:5000 --dry-run=client -o yaml >> deploy_web_svc.yaml
以下のようなマニフェストファイルが出力されます。
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: qiita-sample-web
name: qiita-sample-web
spec:
ports:
- name: 8080-5000
port: 8080
protocol: TCP
targetPort: 5000
selector:
app: 4qiita-sample-svc
type: LoadBalancer
status:
loadBalancer: {}
不要な部分を削除します。
apiVersion: v1
kind: Service
metadata:
labels:
app: qiita-sample-web
name: qiita-sample-web
spec:
ports:
- name: 8080-5000
port: 8080
protocol: TCP
targetPort: 5000
selector:
app: 4qiita-sample-svc
type: LoadBalancer
WebサーバのPodにルーティングするので、selectorをapp: 4qiita-sample-web
に変更します。
apiVersion: v1
kind: Service
metadata:
labels:
app: qiita-sample-web
name: qiita-sample-web
spec:
ports:
- name: 8080-5000
port: 8080
protocol: TCP
targetPort: 5000
selector:
app: 4qiita-sample-web
type: LoadBalancer
今回、ServiceのタイプとしてLoadBalancer
を指定しています。このタイプでデプロイすると、OCIのロードバランサ―を自動的にプロビジョニングしてくれるのですが、少しだけ追加で設定を書く必要があります。追加の設定はmetadata.annotations
に記述します。
apiVersion: v1
kind: Service
metadata:
labels:
app: qiita-sample-web
name: qiita-sample-web
annotations:
oci.oraclecloud.com/load-balancer-type: "lb"
service.beta.kubernetes.io/oci-load-balancer-shape: "flexible"
service.beta.kubernetes.io/oci-load-balancer-shape-flex-min: "10"
service.beta.kubernetes.io/oci-load-balancer-shape-flex-max: "30"
spec:
ports:
- name: 8080-5000
port: 8080
protocol: TCP
targetPort: 5000
selector:
app: 4qiita-sample-web
type: LoadBalancer
DBアクセス用のService
同様に以下のコマンドでひな型を作成します。
$ kubectl create svc clusterip --tcp=3306:3306 --dry-run=clinet -o yaml >> deploy_db_svc.yaml
不要な部分を削除すると以下のようになります。
apiVersion: v1
kind: Service
metadata:
labels:
app: qiita-sample-db
name: qiita-sample-db
spec:
ports:
- name: 3306-3306
port: 3306
protocol: TCP
targetPort: 3306
selector:
app: qiita-sample-db
type: ClusterIP
selectorをDBのDeploymentのラベルに変更します。
apiVersion: v1
kind: Service
metadata:
labels:
app: qiita-sample-db
name: qiita-sample-db
spec:
ports:
- name: 3306-3306
port: 3306
protocol: TCP
targetPort: 3306
selector:
app: 4qiita-sample-db
type: ClusterIP
以上で作成完了です。
なお、WebのPodからはこのService名でDB用のPodにアクセスできます。ですので、qiita-sample-db
という名前でアクセス可能です。
クラスターにデプロイ
作成したマニフェストファイルを適用して、クラスターにアプリケーションをデプロイします。以下のコマンドで適用できます。
$ kubectl apply -f deploy_db.yaml
$ kubectl apply -f deploy_web.yaml
$ kubectl apply -f deploy_web_svc.yaml
$ kubectl apply -f deploy_db_svc.yaml
正しく作成されたかどうか、確認します。
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
4qiita-sample-db 1/1 1 1 2m9s
4qiita-sample-web 3/3 3 3 111s
すべてREADY
になっています。
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP,12250/TCP 3h32m
qiita-sample-db ClusterIP 10.96.157.65 <none> 3306/TCP 5m49s
qiita-sample-web LoadBalancer 10.96.71.82 146.56.42.208 8080:32154/TCP 89s
作成した二つのService(qiita-sample-db
, qiita-sample-web
)があることがわかります。
アクセスしてみる
作成したロードバランサ―の<EXTERNAL-IP>:<PORT>
でアクセスします。以下のように無事に画面が表示されれば成功です。
記事の更新が可能か確かめてみます。
無事に記事の追加ができることが確認できました。
まとめ
少し長くなりましたが、今回はパブリッククラウドのマネージドKubernetesサービスを利用して、自作のウェブアプリを公開するまでの流れを説明しました。最低限のKubernetesの機能しか使っていないので、まだまだ改善するべき点は多々ありますが、とりあえずデプロイするだけなら比較的簡単に可能であることが分かっていただけたかと思います。
今回はDockerfileの中に環境変数の値を埋め込んでいるため、環境変数の値を変更しようとすると毎回コンテナイメージをビルドする必要があり、不便です。Kubernetes側で環境変数を扱えるようにするため、次回はConfigMapについて説明したいと思います。