Oktetoを使用してKubernetesでアプリケーションを開発する方法
著者は、 Write for DOnations プログラムの一環として、 Girls WhoCodeを選択して寄付を受け取りました。
序章
Okteto CLI は、Kubernetesで実行されるアプリケーションのローカル開発エクスペリエンスを提供するオープンソースプロジェクトです。 これを使用すると、ローカルIDEでコードを記述でき、ファイルを保存するとすぐに、変更をKubernetesクラスターにプッシュでき、アプリがすぐに更新されます。 このプロセス全体は、Dockerイメージをビルドしたり、Kubernetesマニフェストを適用したりする必要なしに実行されます。これには、かなりの時間がかかる場合があります。
このチュートリアルでは、Kubernetesネイティブアプリケーションを開発する際に、Oktetoを使用して生産性を向上させます。 まず、Kubernetesクラスターを作成し、それを使用して標準の「HelloWorld」アプリケーションを実行します。 次に、Oktetoを使用して、ローカルに何もインストールしなくても、アプリケーションを開発して自動的に更新します。
前提条件
このチュートリアルを開始する前に、次のものが必要です。
- Kubernetes1.12+クラスター。 このチュートリアルでは、セットアップで3つのノードを持つ DigitalOcean Kubernetes クラスターを使用しますが、別の方法を使用してクラスターを自由に作成できます。
kubectl
およびdoctl
がインストールされ、クラスターと通信するように構成されています。- DockerHubアカウント
- ローカルマシンで実行されているDocker。
ステップ1—HelloWorldアプリケーションを作成する
「HelloWorld」プログラムは、Web開発における昔ながらの伝統です。 この場合、それはすべての要求に「HelloWorld」に応答する単純なWebサービスです。 Kubernetesクラスターを作成したので、Golangで「HelloWorld」アプリを作成し、それをKubernetesにデプロイするために使用するマニフェストを作成しましょう。
最初にホームディレクトリに移動します。
cd ~
次に、hello_world
という名前の新しいディレクトリを作成し、その中に移動します。
mkdir hello_world cd hello_world
お気に入りのIDEまたはテキストエディタを使用して、main.go
という名前で新しいファイルを作成して開きます。
nano main.go
main.go
は、メッセージHello world!
を返すGolangWebサーバーになります。 それでは、次のコードを使用しましょう。
main.go
package main import ( "fmt" "net/http" ) func main() { fmt.Println("Starting hello-world server...") http.HandleFunc("/", helloServer) if err := http.ListenAndServe(":8080", nil); err != nil { panic(err) } } func helloServer(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello world!") }
main.go
のコードは次のことを行います。
- Goソースファイルの最初のステートメントは、
package
名である必要があります。 実行可能コマンドは常にpackage main
を使用する必要があります。 import
セクションは、コードが依存するパッケージを示します。 この場合、文字列操作にはfmt
を使用し、HTTPサーバーにはnet/http
を使用します。main
関数は、バイナリへのエントリポイントです。http.HandleFunc
メソッドは、/
パスへの要求を受信したときにhelloServer
関数を呼び出すようにサーバーを構成するために使用されます。http.ListenAndServe
は、ポート8080
のすべてのネットワークインターフェイスでリッスンするHTTPサーバーを起動します。helloServer
関数には、リクエストハンドラのロジックが含まれています。 この場合、リクエストへの応答としてHello world!
を書き込みます。
Dockerイメージを作成し、Dockerレジストリにプッシュして、Kubernetesがイメージをプルしてアプリケーションを実行できるようにする必要があります。
お気に入りのIDEまたはテキストエディタでDockerfile
という名前の新しいファイルを開きます。
nano Dockerfile
Dockerfile
には、アプリケーションのDockerコンテナーを構築するために必要なコマンドが含まれています。 次のコードを使用してみましょう。
Dockerfile
FROM golang:alpine as builder RUN apk --update --no-cache add bash WORKDIR /app ADD . . RUN go build -o app FROM alpine as prod WORKDIR /app COPY --from=builder /app/app /app/app EXPOSE 8080 CMD ["./app"]
Dockerfile
には、builder
とprod
の2つのステージが含まれています。
builder
ステージには、Goビルドツールが含まれています。 ファイルのコピーとGoバイナリの構築を担当します。prod
ステージが最終画像です。 削除されたOSとアプリケーションバイナリのみが含まれます。
これは従うべき良い習慣です。 アプリケーションとそれを実行するために必要なものだけが含まれているため、本番コンテナはより小さく、より安全になります。
コンテナイメージをビルドします(your_DockerHub_username
をDockerHubユーザー名に置き換えます)。
docker build -t your_DockerHub_username/hello-world:latest
次に、DockerHubにプッシュします。
docker push your_DockerHub_username/hello-world:latest
次に、Kubernetesマニフェスト用の新しいフォルダを作成します。
mkdir k8s
Kubernetesマニフェストを使用するときは、アプリケーションをどのように実行するかをKubernetesに指示します。 今回は、deployationオブジェクトを作成します。 したがって、お気に入りのIDEまたはテキストエディタを使用して新しいファイルdeployment.yaml
を作成します。
nano k8s/deployment.yaml
次のコンテンツでは、okteto/hello-world:latest
Dockerイメージを実行するKubernetesデプロイメントオブジェクトについて説明します。 このコンテンツを新しいファイルに追加しますが、この場合、image
ラベルの後にリストされているokteto
をyour_DockerHub_username
に置き換えます。
〜/ hello_world / k8s / deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: hello-world spec: selector: matchLabels: app: hello-world replicas: 1 template: metadata: labels: app: hello-world spec: containers: - name: hello-world image: your_DockerHub_username/hello-world:latest ports: - containerPort: 8080
デプロイメントマニフェストには、次の3つの主要なセクションがあります。
metadata
は、デプロイメントの名前を定義します。replicas
は、実行するコピーの数を定義します。template
は、Kubernetesに何をデプロイし、どのラベルを追加するかを指示します。 この場合、okteto/hello-world:latest
イメージを持ち、ポート8080
でリッスンし、app: hello-world
ラベルが付いた単一のコンテナーです。 このラベルは、selector
セクションで使用されているものと同じであることに注意してください。
ここで、アプリケーションにアクセスする方法が必要になります。 service オブジェクトを作成することで、Kubernetesでアプリケーションを公開できます。 それを行うためにマニフェストを使い続けましょう。 お気に入りのIDEまたはテキストエディタを使用して、service.yaml
という名前の新しいファイルを作成します。
nano k8s/service.yaml
次のコンテンツは、hello-world
デプロイメントオブジェクトを公開するサービスについて説明しています。このオブジェクトは、内部でDigitalOceanロードバランサーを使用します。
k8s / service.yaml
apiVersion: v1 kind: Service metadata: name: hello-world spec: type: LoadBalancer ports: - protocol: TCP port: 80 targetPort: 8080 name: http selector: app: hello-world
サービスマニフェストには、次の4つの主要なセクションがあります。
metadata
は、サービスに名前を付ける方法をKubernetesに指示します。type
は、Kubernetesにサービスを公開する方法を指示します。 この場合、デジタルオーシャンロードバランサーを介して外部に公開されます。ports
ラベルは、公開するポートと、それらをデプロイにマッピングする方法をKubernetesに指示します。 この場合、ポート80
を外部に公開し、展開内のポート8080
に転送します。selector
は、トラフィックを転送する方法をKubernetesに指示します。 この場合、app: hello-world
ラベルの付いたポッドはすべてトラフィックを受信します。
これで、「HelloWorld」アプリケーションをKubernetesにデプロイする準備が整いました。 次にこれを行います。
ステップ2—HelloWorldアプリケーションをデプロイする
このステップでは、「Hello World」アプリケーションをKubernetesにデプロイしてから、正しく機能していることを検証します。
アプリケーションをKubernetesにデプロイすることから始めます。
kubectl apply -f k8s
次の出力が表示されます。
Outputdeployment.apps "hello-world" created service "hello-world" created
約1分後、アプリケーションのIPを取得できるようになります。 次のkubectl
コマンドを使用して、サービスを確認します。
kubectl get service hello-world
Kubernetesサービスオブジェクトを一覧表示する次のような出力が表示されます。 EXTERNAL-IP
列にあるアプリケーションのIPに注意してください。
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-world ClusterIP your_cluster_ip your_external_ip 8080/TCP 37s
ブラウザを開き、「HelloWorld」アプリケーションにリストされているyour_external_ip
に移動します。 次の手順に進む前に、アプリケーションが稼働していることを確認してください。
この瞬間まで、Kubernetesを使用してアプリケーションを開発するためのかなり伝統的な方法をたどってきました。 今後は、アプリケーションのコードを変更する場合は常に、新しいDockerイメージをビルドしてプッシュし、そのイメージをKubernetesからプルする必要があります。 このプロセスにはかなりの時間がかかる場合があります。 Oktetoは、この開発の内部ループを合理化するように設計されました。 Okteto CLIを見て、それがどのように役立つかを見てみましょう。
ステップ3—OktetoCLIのインストール
Okteto CLIをインストールすることで、Kubernetes開発の生産性が向上します。 Oktetoコマンドラインインターフェースは、アプリケーションコードの変更をKubernetesで実行されているアプリケーションに同期できるオープンソースプロジェクトです。 前の手順で行ったように、コンテナーをコミット、ビルド、プッシュ、または再デプロイしてアプリケーションをテストしなくても、お気に入りのIDE、デバッガー、またはコンパイラーを引き続き使用できます。
MacOSまたはLinuxマシンにOktetoCLIをインストールするには、次のコマンドを実行します。
curl https://get.okteto.com -sSfL | sh
このコマンドを詳しく見てみましょう。
curl
コマンドは、サーバーとの間でデータを転送するために使用されます。-s
フラグは、出力を抑制します。-S
フラグはエラーを示します。-f
フラグを使用すると、HTTPエラーでリクエストが失敗します。-L
フラグは、リクエストをリダイレクトに従わせます。|
オペレーターは、この出力をsh
コマンドにパイプします。このコマンドは、最新のokteto
バイナリをダウンロードしてローカルマシンにインストールします。
Windowsを実行している場合は、代わりに Webブラウザからファイルをダウンロードし、手動で$PATH
に追加することができます。
Okteto CLIがインストールされると、「HelloWorld」アプリケーションを開発モードにする準備が整います。
ステップ4—HelloWorldアプリケーションを開発モードにする
Okteto CLIは、Kubernetesクラスターで実行されているアプリケーションをマシンにあるコードと交換するように設計されています。 そのために、OktetoはOktetoマニフェストファイルから提供された情報を使用します。 このファイルは、ローカルコードとスワップするKubernetesデプロイメントオブジェクトを宣言します。
お気に入りのIDEまたはテキストエディタを使用して、okteto.yaml
という名前の新しいファイルを作成します。
nano okteto.yaml
デプロイメントオブジェクト名、使用するDockerベースイメージ、およびシェルを定義する基本的なマニフェストを作成しましょう。 後でこの情報に戻ります。 次のサンプルコンテンツファイルを使用します。
okteto.yaml
name: hello-world image: okteto/golang:1 workdir: /app command: ["bash"]
次のコマンドを実行して、アプリケーションを開発モードにする準備をします。
okteto up
Output ✓ Development environment activated ✓ Files synchronized Namespace: default Name: hello-world Welcome to your development environment. Happy coding! default:hello-world /app>
okteto up
コマンドは、「HelloWorld」アプリケーションを開発環境にスワップします。これは次のことを意味します。
- Hello Worldアプリケーションコンテナーは、Dockerイメージ
okteto/golang:1
で更新されます。 このイメージには、「Hello World」アプリケーションをビルド、テスト、デバッグ、および実行するために必要な開発ツールが含まれています。 - ファイル同期サービスは、ローカルファイルシステムとアプリケーションポッドの間で変更を最新の状態に保つために作成されます。
- 開発環境でリモートシェルが起動します。 これで、ローカルマシンにいるかのように、アプリケーションをビルド、テスト、および実行できます。
- リモートシェルで実行するプロセスが何であれ、元の「Hello World」アプリケーションポッドと同じ着信トラフィック、同じ環境変数、ボリューム、またはシークレットを取得します。 これにより、非常に現実的な本番環境のような開発環境が実現します。
同じコンソールで、次のように、通常どおりに(Dockerイメージをビルドしてプッシュせずに)アプリケーションを実行します。
go run main.go
OutputStarting hello-world server...
アプリケーションを初めて実行するときに、Goは依存関係をダウンロードしてアプリケーションをコンパイルします。 以前と同じように、ブラウザを開いてアプリケーションのページを更新することにより、このプロセスが終了してアプリケーションをテストするのを待ちます。
これで、Kubernetesで直接開発を開始する準備が整いました。
ステップ5—Kubernetesで直接開発する
「HelloWorld」アプリケーションに変更を加えてから、これらの変更がKubernetesにどのように反映されるかを見てみましょう。
お気に入りのIDEまたはテキストエディタでmain.go
ファイルを開きます。 たとえば、別のコンソールを開いて、次のコマンドを実行します。
nano main.go
次に、応答メッセージをHello world from DigitalOcean!
に変更します。
main.go
package main import ( "fmt" "net/http" ) func main() { fmt.Println("Starting hello-world server...") http.HandleFunc("/", helloServer) if err := http.ListenAndServe(":8080", nil); err != nil { panic(err) } } func helloServer(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello world from DigitalOcean!") }
ワークフローが変わるのはここです。 イメージをビルドしてコンテナを再デプロイして「HelloWorld」アプリケーションを更新する代わりに、Oktetoは変更をKubernetesの開発環境に同期します。
okteto up
コマンドを実行したコンソールから、CTRL + C
を押して、go run main.go
の実行をキャンセルします。 次に、アプリケーションを再実行します。
default:hello-world /app> go run main.go
OutputStarting hello-world server...
ブラウザに戻り、「HelloWorld」アプリケーションのページをリロードします。
コードの変更は、コミット、ビルド、プッシュを必要とせずに、Kubernetesに即座に適用されました。
結論
Okteto は、ボタンをクリックするだけで、Kubernetesクラスターをフル機能の開発プラットフォームに変換します。 このチュートリアルでは、 Okteto CLI をインストールして構成し、コードを入力するのと同じ速さでコードの変更をKubernetesで直接繰り返すようにしました。 これで、 Oktetoサンプルリポジトリにアクセスして、さまざまなプログラミング言語やデバッガーでOktetoを使用する方法を確認できます。
また、Kubernetesクラスタをチームと共有する場合は、同じクラスタで作業している他の開発者から分離されるように設定された安全なKubernetes名前空間へのアクセスを各メンバーに許可することを検討してください。 この優れた機能は、 DigitalOcean KubernetesMarketplaceのOktetoAppによっても提供されます。