KubernetesでGolangのPodにHttp/2を通信
概要
KubernetesでGolangのPodにHttp/2を通信させる。
NginxにtlsでHttp/2通信すことできたから、Golangも楽勝でしょ♪
とか思ってたらそこそこ詰まったのでメモしとくっす
基本的には以下2つで構築した環境を前提に記載する
自己証明書関連の設定
自己証明書の作成とSecret登録
minikubeでTLS通信して裏側のNginxでHTTP/2.0を受けるの「自己証明書の作成」=>「自己証明書をSecretsとして登録」の通りにして、go.ucwork.local
にtls通信できるように準備する
証明書をgolangのpodに登録
volumesに証明書を登録したsecretを設定し、podの任意のパスにマウントする。
apiVersion: v1 kind: Service metadata: name: go labels: app: go spec: ports: - port: 443 selector: app: go tier: backend type: LoadBalancer --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: go-pv-claim labels: app: go spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi --- apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata: name: go labels: app: go spec: selector: matchLabels: app: go tier: backend strategy: type: Recreate template: metadata: labels: app: go tier: backend spec: containers: - image: shintaro0123/golang:latest name: go env: - name: GO_DB_HOST value: go-mysql - name: GO_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password ports: - containerPort: 443 name: go volumeMounts: - name: go-persistent-storage mountPath: /var/www/html - name: tls-cert # ②podの好きなパスにマウントする mountPath: /go/tls # ↑ volumes: - name: go-persistent-storage persistentVolumeClaim: claimName: go-pv-claim - name: tls-cert # ①作成したsecretを指定 secret: # ↑ secretName: tls-secret # ↑
Golangファイルの作成
http2のパッケージ取得
$ go get -u golang.org/x/net/http2
http2を受けることができるようgoファイル作成
kubernetesでローカル環境にNGINX, golang, MySQL環境作ってみるこの時の記述に引っ張られてDB関連のことも記載されているが、
ポイントは以下2点。それ以外は消しちゃってもいい世界
- マウントした証明書のパスを指定してListen
srv.ListenAndServeTLS("/go/tls/tls.crt", "/go/tls/tls.key")
- http2で通信を受けることができように設定
http2.ConfigureServer(srv, nil)
最初ネットで調べてListenAndServeTLS(":443", "/go/tls/tls.crt", "/go/tls/tls.key")
これでなんとかやっていたが、どうしても「CrashLoopBackOff」になりpodが立ち上がらなかった・・・
そもそもgo初心者なんで、まぁ細々したことは学習しながら学んでいこう。
main.go
package main import ( "database/sql" "fmt" "log" "net/http" "os" "golang.org/x/net/http2" _ "github.com/go-sql-driver/mysql" ) func main() { mux := http.NewServeMux() mux.HandleFunc("/", handler) srv := &http.Server{ Addr: ":443", Handler: mux, } http2.VerboseLogs = true http2.ConfigureServer(srv, nil) log.Fatal(srv.ListenAndServeTLS("/go/tls/tls.crt", "/go/tls/tls.key")) } func handler(w http.ResponseWriter, r *http.Request) { /** URLパス表示 */ w.Write([]byte("url path is " + r.URL.Path[1:] + "\n")) /** DB接続 */ var dbConnectQuery string dbConnectQuery = "root:" + os.Getenv("GO_DB_PASSWORD") + "@tcp(" + os.Getenv("GO_DB_HOST") + ":3306)/ucwork" db, err := sql.Open("mysql", dbConnectQuery) if err != nil { panic(err.Error()) } defer db.Close() // 関数がリターンする直前に呼び出される rows, err := db.Query("SELECT * FROM user") // if err != nil { panic(err.Error()) } columns, err := rows.Columns() // カラム名を取得 if err != nil { panic(err.Error()) } values := make([]sql.RawBytes, len(columns)) scanArgs := make([]interface{}, len(values)) for i := range values { scanArgs[i] = &values[i] } for rows.Next() { err = rows.Scan(scanArgs...) if err != nil { panic(err.Error()) } var value string for i, col := range values { // Here we can check if the value is nil (NULL value) if col == nil { value = "NULL" } else { value = string(col) } w.Write([]byte(columns[i] + ": " + value + "\n")) } fmt.Println("-----------------------------------") } }
ビルドする
kubernetesでローカル環境にNGINX, golang, MySQL環境作ってみる
ここの「golang」にあるように、ビルドしてデプロイ
$ env GOOS=linux GOARCH=amd64 go build main.go
$ # 生成されたmainをpodに反映させる
検証する
curlでアクセスしてみるとHTTP/2でアクセスできた!!
$ curl --resolve go.ucwork.local:443:`minikube ip` -k https://go.ucwork.local -v ... > GET / HTTP/2 > Host: go.ucwork.local > User-Agent: curl/7.54.0 > Accept: */* > * Connection state changed (MAX_CONCURRENT_STREAMS updated)! < HTTP/2 200 < content-type: text/plain; charset=utf-8 < content-length: 66 < date: Sat, 30 Mar 2019 20:28:25 GMT < url path is id: 1 name: taro id: 2 name: jiro id: 3 name: hanako * Connection #0 to host go.ucwork.local left intact
まとめ
早くgolang自体の勉強したいのになかなか環境構築で手こずるw
やっと最低限くらいができたんで、あとはSKAFFOLD使ったローカル開発方式だけまとめて、golang自体の勉強にスイッチしよう!!!