注意
この記事で用いているソースコードの大半はchatGPT(GPT-4)を用いて生成されています。あくまでサンプルと思って読んでください。
MySQLをデプロイ
以下のyamlをdeploy.yaml
という名前で保存します。基本的にはkindに合わせてファイルを分けたりするのですが、面倒なのでふっ飛ばします。
やってることは主に以下の通りです。
- MySQLの初期データを設定
- MySQLのパスワードを設定
- ClusterIPを用いてクラスタ内にMySQLを3306で公開
apiVersion: v1 kind: ConfigMap metadata: name: db-init-configmap data: init.sql: | CREATE DATABASE IF NOT EXISTS app; USE app; CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com'); INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com'); INSERT INTO users (name, email) VALUES ('Charlie', 'charlie@example.com'); --- apiVersion: v1 kind: Secret metadata: name: sql-secret type: Opaque data: # パスワードをbase64でエンコードした値 password: cGFzc3dvcmQ= --- apiVersion: apps/v1 kind: Deployment metadata: name: mysql-deployment labels: app: mysql spec: replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: 'mysql:8' volumeMounts: - name: sql-init-config mountPath: /docker-entrypoint-initdb.d env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: sql-secret key: password ports: - containerPort: 3306 volumes: - name: sql-init-config configMap: name: db-init-configmap items: - key: init.sql path: init.sql --- apiVersion: v1 kind: Service metadata: name: mysql spec: type: ClusterIP selector: app: mysql ports: - port: 3306 targetPort: 3306 protocol: TCP
以下コマンドを叩いて起動します
> kubectl apply -f deploy.yaml # configmap/db-init-configmap created # secret/sql-secret created # deployment.apps/mysql-deployment created # service/mysql created > kubectl get svc # NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE # mysql ClusterIP 10.97.17.57 <none> 3306/TCP 0m > kubectl get pods # NAME READY STATUS RESTARTS AGE # mysql-deployment-5c7dbf6db5-hpfvh 1/1 Running 0 0m
Goのアプリをデプロイ
イメージの作成
まずはコードを用意します。(以下コードはすべてGPTが生成したものです)
package main import ( "database/sql" "encoding/json" "fmt" "log" "net/http" _ "github.com/go-sql-driver/mysql" ) type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"` CreatedAt string `json:"created_at"` } func getUsers(db *sql.DB) ([]User, error) { rows, err := db.Query("SELECT id, name, email, created_at FROM users") if err != nil { return nil, err } defer rows.Close() var users []User for rows.Next() { var u User if err := rows.Scan(&u.ID, &u.Name, &u.Email, &u.CreatedAt); err != nil { return nil, err } users = append(users, u) } return users, nil } func handler(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { users, err := getUsers(db) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(users) } } func main() { db, err := sql.Open("mysql", "root:password@tcp(mysql:3306)/app") if err != nil { log.Fatal(err) } defer db.Close() http.HandleFunc("/users", handler(db)) fmt.Println("Server is running on port 8080...") log.Fatal(http.ListenAndServe(":8080", nil)) }
- main関数の以下の部分について補足します。先ほどMySQLをクラスタ内に公開しました。このときサービス名をmysql、公開ポートを3306にしていたので接続設定は
mysql:3306
になります。mysqlという名前で名前解決してMySQLのPodにたどり着けます
db, err := sql.Open("mysql", "root:password@tcp(mysql:3306)/app")
以下コマンドを実行して初期化します
go mod init xxx go mod tidy
次にDockerfileを作ってイメージを作成します。ビルドに使っているイメージのバージョンに注意してください
FROM golang:1.18 AS builder WORKDIR /app/ COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -trimpath -ldflags "-w -s" -o app main.go # --------------------------------------------------- FROM debian:bullseye-slim as deploy RUN apt-get update COPY --from=builder /app/app . CMD ["./app"]
ビルドしてpushします。
docker build . -t abc/xxx # 自分のアカウントに合わせてください docker image push abc/xxx:latest # docker.io/abc/xxx という感じになります
pushしたイメージからPodを作成する
最後にpushしたイメージをもとにyamlを書きます。imageの部分は環境に合わせて自分で書いてください。
apiVersion: apps/v1 kind: Deployment metadata: name: appname-deployment spec: replicas: 2 selector: matchLabels: app: appname template: metadata: labels: app: appname spec: containers: - name: appname image: # ここを環境に合わせる。例通りだとdocker.io/abc/xxxになる ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: appname-service spec: type: NodePort ports: - port: 8080 targetPort: 8080 protocol: TCP selector: app: appname
デプロイしてNodePortを調べる。
> kubectl apply -f goapp.yaml deployment.apps/appname-deployment configured service/appname-service unchanged > kubectl get pods NAME READY STATUS RESTARTS AGE appname-deployment-57cd49c8c8-f9vrf 1/1 Running 0 32m appname-deployment-57cd49c8c8-jgrwg 1/1 Running 0 32m mysql-deployment-5c7dbf6db5-hpfvh 1/1 Running 0 38m > kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE appname-service NodePort 10.105.150.252 <none> 8080:32340/TCP 35m kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27h mysql ClusterIP 10.97.17.57 <none> 3306/TCP 43m
http://localhost:32340/users
にアクセスして以下の情報が表示されたら成功
[{"id":1,"name":"Alice","email":"alice@example.com","created_at":"2024-03-27 15:12:53"},{"id":2,"name":"Bob","email":"bob@example.com","created_at":"2024-03-27 15:12:53"},{"id":3,"name":"Charlie","email":"charlie@example.com","created_at":"2024-03-27 15:12:53"}]
おしまい