
GMO kitaQ勤務の桑原です。
RubyKaigi 2019 Day3は私と中村槙吾がチャレンジャーになります。
今回はk8sとIstioの設定に関するお題にチャレンジします。
そもそもk8s自体二人とも業務でもプライベートでも経験はありませんが、
なんとかなるだろ精神で頑張ります!
朝9時に会場到着して朝食ゲット。
福岡人だけど、ここの明太子うめえ!
力もつけたところで、本日のお題はコチラ。
Q0 ~ Q2までの3問クリアでチャレンジ成功。
まず用語が分からねぇ・・・
ちなみに本日のチャレンジャー2名のスキルセットはこんな感じ。
-K: 小規模ながらDockerで社内向けサービス構築経験アリ。k8sは前日にkubesprayで初めて構築したレベル。
istio,サービスメッシュはwhat?レベル。
-N: k8sをチャレンジ3日前にまともに触り始めました。istio,サービスメッシュは今回のチャレンジが初。
10時になったので、これから目標3問クリアを目指して頑張ろー!
まずはQ0
80番ポートをlistenするgoのアプリをコンテナ上で実行せよ、とのお題。
# RubyKaigiでGoを使う勇気が試される
それを3つのコンテナで行い、80番ポートにアクセスしたら、それぞれ
RubyKaigi,{1}
RubyKaigi,{2}
RubyKaigi,{3}
とリプライしてくれればお題クリア。
Kの頭の中
マルチステージでビルドしてイメージ作ろう。
3つあるからdocker-compose使うほうが利口だろうか?
でもdocker-composeでマルチステージビルドできるのか?
分からんからmain.goとDockerfile、それぞれ3つ作るか。
てことで、3つ用意。以下の感じで3つ分dockerビルド。
main1.go
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "RubyKaigi,{1}")
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":80", nil))
}
Dockerfile
FROM golang:latest as builder1
ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64
WORKDIR /work
COPY . .
RUN go build main1.go
# runtime image
FROM alpine
RUN apk add --no-cache ca-certificates
COPY --from=builder1 /work /app
EXPOSE 80
CMD /app/main1
# docker build -t my/myapp1 .
# docker run -p 8181:80 -d -t myapp1
ローカルの8181から80ポートにフォワードしてRubyKaigi,{1} のレスポンスあり。
Q1以降でk8sからrunするので、確認用にrunした上記は削除。
実は最初はhttp-serverというnameでbuildしていました。
しかし、Q1以降でk8s上にdeploymentをcreateしようとすると、
DockerHubからpullしようとしてエラーになったため、
ローカルからpullする際のお作法に従いmy/myapp1にrenameしています。
11時前にQ0クリア!
今のところ順風満帆か!?
しかしQ1以降は完全にワカメ。
ひとまずQ0でbuildしたmy/myapp{1,2,3}たちをrunしよう。
ただし、google先生曰く、istio-injection=enabledをラベルしたnamespace上で
コンテナを起動させないと、自動でistioがサイドカーとしてpod内に作られないようだ。
まあ、istioctlを使用して狙いうちでサイドカーをinjectすることもできるらしいが。
# kubectl get namespace -L istio-injection
NAME STATUS AGE ISTIO-INJECTION
default Active 2d12h enabled
istio-system Active 2d12h disabled
kube-node-lease Active 2d12h
kube-public Active 2d12h
kube-system Active 2d12h
してみると、default namespaceで既にistio-injection=enabled済みなので、
ここでコンテナ起動することにしよう。
てことでまずはdeploymentのyamlを作成。
myapp1-deploy.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myapp1
spec:
replicas: 1
template:
metadata:
labels:
app: myapp1
spec:
containers:
- name: myapp1
image: my/myapp1:1.0
ports:
- containerPort: 80
# kubectl apply -n default -f myapp1-deploy.yml
kubectl get deploy, kubectl get podsして
deploymentもpodも正常に構築できていること確認。
これを3つ分作成。
次にgateway/virtualserviceのyamlを作成してapplyする必要があるようだ。 by google先生。
(注)この時点ではgateway/virtualserviceの役割分かってない。何ならserviceの役割も分かってない。
見よう見まねで以下のyamlを作成して、それぞれapply。
gateway.yml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: myapp-gateway
namespace: default
spec:
selector:
istio: ingressgateway
servers:
- port:
name: http
number: 80
protocol: HTTP
hosts:
- "*"
virtualservice.yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp-vsvc
namespace: default
spec:
gateways:
- "myapp-gateway"
hosts:
- "*"
http:
- match:
route:
- destination:
host: "*"
port:
number: 8181
kubectl get gateway/virtualgatewayして、構築できたことを確認。
localhost:8181にcurlしてみるが失敗…
# curl http://localhost:8181
curl: (7) Failed to connect to localhost port 8181: Connection refused
ここから泥沼にはまる。
serviceをapplyしていないとダメっぽいので、以下のserviceをtype=cluster ipも起動するも、
やっぱりcurlで8181からデータ取れない。
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
namespace: default
labels:
name: myapp
spec:
selector:
app: myapp
# type: NodePort
ports:
- name: myapp
protocol: TCP
port: 80
targetPort: 8181
結局、解決できずにこのままタイムアップ!
残念ながらistioの問題は1問も解けず…不完全燃焼という感じ。
k8s/istioのネットワーク周りの概念がよく分かってないまま構築したことが敗因。
service/gateway/virtualgatewayココら辺。
理解できないまま突っ込んだので、エラーが出てもその対処すらも見当がつかなかった。
ネットワーク周りを理解したうえで、再チャレンジしてみたい。
さらなるアップデートを乞うご期待!!!