GitHubアカウントのみ！Codespacesを使ったKubernetes入門

# はじめに

CodespacesはGitHubが提供する**クラウド開発環境**です[1]。Ubuntu20.04の仮想マシンと、WEB上で動作するVSCodeを無料で利用する事ができます。クレジットカード登録は不要で、毎月の無料枠を使い切ると強制停止してくれるため安心です[2]。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324111/5ef2d66d-387b-cc43-2f79-000aadd5fcba.png)

Codespacesでは仮想マシンを利用できるため、ほぼすべてのプログラミング言語の開発を行うことができます。この柔軟性と手軽さを活かして今回はKubernetesの入門記事を書きたいと思います。


1. GitHubアカウントの作成
1. Codespacesの起動
1. Minikubeを用いた環境の構築
1. Kubernetes入門


# 1. Githubアカウントの作成

GitHubアカウントを[Join GitHub](https://github.com/signup)で作成してください。

# 2. Codespacesの起動

[公式クイックスタート](https://docs.github.com/ja/codespaces/getting-started/quickstart)を参考に進めます。

Codespacesは`設定が含まれたGitHubリポジトリ`から起動します。[公式テンプレートリポジトリ](https://github.com/github/haikus-for-codespaces)に移動します。

ログインしていると、[User this template]ボタンがされているはずです。クリックしさらに[Open in a codespace]を選択します。

![スクリーンショット 2023-06-27 213905.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324111/d0e32707-32dc-5d9e-b9ec-c96cd5a2523b.png)

これだけでターミナルが使える開発環境が起動できます。VSCodeの利用感もアプリ版と遜色ないレベルです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324111/9d616e76-9079-649c-6cfd-48b33710b021.png)

ターミナルで`pwd`コマンドや`ls`コマンドを実行してみます。チュートリアルではnodeJSで構築されたデモアプリケーションが含まれており、`pachage.json`などが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324111/3ffb9585-afd2-347f-8ee6-7386956c379e.png)

試しにデモアプリを起動してみます。`npm run dev`を実行してください。すると、「ブラウザーで開く」とポップアップが表示されるのでクリックします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324111/038c4b7c-2475-881b-1fa6-16830a6795ee.png)

すると、別タブで簡単にデモアプリケーションにアクセスできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324111/7d0384aa-d68d-4777-5fdf-ad98af122940.png)

VSCodeに戻り、ターミナルタブの隣のポートタブをクリックします。すると起動中のポートが確認できます。初期設定ではPrivateとなっているため、同じGithubアカウントでログインしたブラウザのみアクセスできます。これを右クリックでPublicとすると一時的に公開することもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324111/47922eca-6397-6fb1-9df3-e56070c0a956.png)



# 3. Minikubeを用いた環境の構築

今回は、Kubernetes入門のため、Minikubeを利用します。

:::note info
minikubeはローカルで実行できるKubernetesであり、容易にKubernetesの学習と開発を行えることに重点を置いています。必要なのはDocker、または仮想マシンの実行環境だけです。[3]
:::

[公式ドキュメント](https://minikube.sigs.k8s.io/docs/start/)を元に環境を構築します。

Debianパッケージをダウンロードし、インストールします。ブラウザ版のVSCodeでもコピペ可能です。


```bash
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube_latest_amd64.deb
sudo dpkg -i minikube_latest_amd64.deb
```




インストールができたか確認を行います。

```bash
@abek15 ➜ /workspaces/haikus-for-codespaces (main) $ minikube version
minikube version: v1.30.1
commit: 08896fd1dc362c097c925146c4a0d0dac715ace0
```

`minikube start`コマンドでminikubeを起動します。このCodesapceテンプレートにはDockerが導入済みのため、Dockerイメージのpullなどが始まります。

```
@abek15 ➜ /workspaces/haikus-for-codespaces (main) $ minikube start
😄  minikube v1.30.1 on Ubuntu 20.04 (docker/amd64)
✨  Automatically selected the docker driver. Other choices: ssh, none
📌  Using Docker driver with root privileges
👍  Starting control plane node minikube in cluster minikube
🚜  Pulling base image ...
💾  Downloading Kubernetes v1.26.3 preload ...
    > preloaded-images-k8s-v18-v1...:  397.02 MiB / 397.02 MiB  100.00% 22.47 M
    > gcr.io/k8s-minikube/kicbase...:  373.53 MiB / 373.53 MiB  100.00% 7.81 Mi
🔥  Creating docker container (CPUs=2, Memory=2200MB) ...
🐳  Preparing Kubernetes v1.26.3 on Docker 23.0.2 ...
    ▪ Generating certificates and keys ...
    ▪ Booting up control plane ...
    ▪ Configuring RBAC rules ...
🔗  Configuring bridge CNI (Container Networking Interface) ...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🔎  Verifying Kubernetes components...
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
```

起動が完了したら、`kubectl get nodes`を実行します。すると単一ノードでクラスタが構築されていることが確認できます。

```
@abek15 ➜ /workspaces/haikus-for-codespaces (main) $ kubectl get nodes
NAME       STATUS   ROLES           AGE    VERSION
minikube   Ready    control-plane   117s   v1.26.3
```

:::note info
`kubectl`コマンドは、Dockerにおける`docker`コマンドと同じで、Kubernetesを操作するコマンドです。Podの起動・削除・ログの確認、クラスタの操作など、ほぼ全ての操作で使うコマンドです。
:::


# 4. Kubernetes入門

それでは、Kubernetesで最も使われるPod, Deployment, Serviceを作成します。

:::note info
Kubernetes Pod は、1 つ以上の Linux® コンテナの集合体で、Kubernetes アプリケーションの最小単位です。[4]　一般的には1Pod、1コンテナとなるケースが多いため、初めのうちはPod＝コンテナと理解してよいと思います。
:::

## Nginxの構築

作業用のディレクトリを作成します。

```
mkdir /workspaces/k8s-workshop
```

作成した作業ディレクトリをVSCodeで開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324111/587612cb-b348-10fa-4ecd-a4a364244f7c.png)

`test_pod.yaml`を作成します。今後、ファイルの編集はVSCodeのエクスプローラーとエディタで行うと便利です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324111/c78b2a20-77f9-ddbf-de25-5fa727f4dd4e.png)

以下の内容を記述します。初めのうちは冗長な記述と感じるかもしれませんが、Kubernetesのアーキテクチャを利用するため必要な記述になります。このように、Kubernetesではyamlファイル（**マニフェスト**）を用いてリソースを定義します。

```yaml
apiVersion: v1
# リソースの種類
kind: Pod
metadata:
  name: test-pod
  labels:
    app: test-app
spec:
  containers:
    # Pod内で起動するコンテナの情報
    - name: web
      image: nginx:1.25.1 # dockerでのイメージ指定と同様
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
```

それでは、Podのマニフェストをクラスタに適用します。

```bash
@abek15 ➜ /workspaces/k8s-workshop $ kubectl apply  -f test_pod.yaml 
pod/test-pod created
```

Podが作成されたか確認します。test-podがRunningになっていれば正常です。

```
@abek15 ➜ /workspaces/k8s-workshop $ kubectl get pod 
NAME       READY   STATUS    RESTARTS   AGE
test-pod   1/1     Running   0          58s
```

コンテナは作成できましたが、この状態ではクラスタ外部からアクセスすることはできません。そこで、`Service`というリソースを用いてPodをクラスタ外部からアクセスできるようにします。

```yaml test_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: test-service
  labels:
    app: test-app
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 80
    nodePort: 30080
    protocol: TCP
  selector:
    app: test-app
```

:::note info
`targetPort:`は、コンテナで起動するアプリケーションのポートに合わせて指定します。80/tcpなどの`well-known port`が多いです。`port:`は、Pod間で通信を行う際に利用するポートで自由に指定できます。8000＋well-knownを慣例で使うことが多いです。`type:nodePort`とした上で`nodePort:`を指定すると、Kubernetesノードのホストで30080/tcpが起動し、コンテナにフォワーディングされます。
:::


マニュフェストをApplyします。

```bash
@abek15 ➜ /workspaces/k8s-workshop $ kubectl apply  -f test_service.yaml 
service/test-service created
```


今回はminikubeを用いているため、minikubeのノード情報を取得します。`minikube service --all`で確認するとノードのIPは192.168.49.2で`http://192.168.49.2:30080`にアクセスするとサービスにアクセスできます。

```
@abek15 ➜ /workspaces/k8s-workshop $ minikube service --all
|-----------|------------|-------------|--------------|
| NAMESPACE |    NAME    | TARGET PORT |     URL      |
|-----------|------------|-------------|--------------|
| default   | kubernetes |             | No node port |
|-----------|------------|-------------|--------------|
😿  service default/kubernetes has no node port
|-----------|--------------|-------------|---------------------------|
| NAMESPACE |     NAME     | TARGET PORT |            URL            |
|-----------|--------------|-------------|---------------------------|
| default   | test-service |        8080 | http://192.168.49.2:30080 |
|-----------|--------------|-------------|---------------------------|
🎉  Opening service default/test-service in default browser...
👉  http://192.168.49.2:30080
```

curlコマンドで確認すると、期待通りNginxが起動していることが判ります。

```
@abek15 ➜ /workspaces/k8s-workshop $ curl http://192.168.49.2:30080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
```


ブラウザでも確認したいですが、Codesapces環境のIP（192.168.49.2）に直接接続できません、そこで、`kubectl`コマンドでポートフォワードを行います。

```
@abek15 ➜ /workspaces/k8s-workshop $ kubectl port-forward service/test-service 8080:8080
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
```

「ブラウザで開く」ポップアップをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324111/7982def8-27ee-e745-fc72-6de49f86da2d.png)

すると別タブでNginxが確認できます。


# おわりに

Codespacesを使用してKubernetes環境を構築し、最小のリソース単位であるPodの起動を行いました。Githubアカウントのみで実施できるため、Kubernetes入門の敷居を下げれたらと思い執筆しました。

今回の記事では、容易に体験できる、に重きを置いたため、詳細な説明は省いています。kubectl、namespace、deployment、labelなど、気になったキーワードを調べ、構築した環境で試して頂ければと思います。

主題ではありませんが、Codesapcesを利用すると、OSや権限によらず、一律な環境を利用できるため、学習やハンズオンに最適だと感じました。

# 参考

- [1] Github, "Codespaces", https://github.co.jp/features/codespaces
- [2] Github, "GitHub Codespaces の請求について", https://docs.github.com/ja/billing/managing-billing-for-github-codespaces/about-billing-for-github-codespaces#monthly-included-storage-and-core-hours-for-personal-accounts
- [3] The Kubernetes Authors, "minikube start", https://minikube.sigs.k8s.io/docs/start/
- [4] Red Hat, "Inc., What is a Kubernetes pod?", https://www.redhat.com/en/topics/containers/what-is-kubernetes-pod