Kubernetes:通过 minikube 安装单机测试环境
官网
https://kubernetes.io/docs/tasks/tools/install-minikube/
https://kubernetes.io/docs/tasks/tools/install-kubectl/
https://kubernetes.io/docs/setup/learning-environment/minikube/
Kubernetes 组件
- kubeadm:CLI 命令,用于安装初始化 Kubernetes 集群,添加新节点(minikube 会用到 kubeadm)
- kubectl:CLI 命令,用于操作集群,kubectl create/apply/scale/get/delete/exec/logs/etc
- Master:控制节点,包括 API Server、Scheduler、Controller Manager、etcd 等
- Node:计算节点,包括 Kubelet、Kube-Proxy、Container Runtime 等
- Add-On:除 Master、Node 的核心组件外还有一些推荐的可选组件,如 DNS、Dashboard、CNI 等等
- API Server:资源操作的唯一入口,REST API,无论外部如 kubectl 还是内部如 scheduler、controller、etcd、kubelet 都是通过 API Server 通信,支持 authentication/authorization
- Scheduler:负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上
- Controller Manager:控制管理 Namespace、ServiceAccount、ResourceQuota、Replication、Volume、NodeLifecycle、Service、Endpoint、DaemonSet、Job、Cronjob、ReplicaSet、Deployment 等等
- etcd:high-available distributed key-value store,用于保存集群的状态,提供 watch for changes 功能
- Kubelet:负责维护容器的生命周期,通过 API Server 把状态告知 Master,同时负责 Volume (CVI) 和网络 (CNI) 的管理
- Kube-Proxy:网络代理和负载均衡,主要用于帮助 service 实现虚拟 IP
- Container Runtime:管理镜像,运行 Pod 和容器,最常用的是 Docker
- Registry:存储镜像
- DNS:为集群提供 DNS 服务(Kube-DNS、CoreDNS)
- Dashboard:提供 Web UI
- Container Resource Monitoring:cAdvisor + Kubelet、Prometheus、Google Cloud Monitoring
- Cluster-level Logging:Fluentd
- CNI:Container Network Interface(Flannel、Calico)
- CSI:Container Storage Interface
- Ingress Controller:为服务提供外网入口
Kubernetes 是 Go 语言编写的
Kubernetes 概念
- Pod:可以创建、调度、部署、管理的最小单位,Pod 包含一个或多个紧耦合的 container,并共享 hostname、IPC、network、storage 等
- ReplicaSet:确保 Pod 以指定的副本个数运行,和 Replication 的唯一区别是对选择器的支持不一样
- Deployment:用于管理 Pod、ReplicaSet,可以实现 Deploy/Scaling/Upgrade/Rollback
- Service:对外提供一个虚拟 IP,后端是一组有相同 Label 的 Pod,并在这些 Pod 之间做负载均衡(ClusterIP、NodePort、LoadBalancer 等几种配置),即负责转发数据到 Pod
- Ingress:链接多个 Service 作为统一入口,根据不同的路径,将数据转发到不同的 Service
- ConfigMap:用于解耦部署与配置的关系,即 Deployment、Pod 等不需要定义好配置,只需要指定对应的 ConfigMap,具体的内容由 ConfigMap 决定
- Secrets:ConfigMap 存储不敏感的信息,而 Secrets 用于存储敏感信息,Secrets 以加密的形式存储(可能是存在 etcd 中),当 Secrets 挂载到 Pod 时,会被解密,并且实质上是存在内存中,可以以文件的形式挂载
以上这些都需要通过 yaml 文件定义(这些文件也被称为 Manifest),然后通过 kubectl create -f xxx.yaml 启动
Minikube Features
Minikube 用于创建单机版的 Kubernetes
- DNS
- NodePorts
- ConfigMaps and Secrets
- Dashboards
- Container Runtime: Docker, CRI-O, and containerd
- Enabling CNI (Container Network Interface)
- Ingress
Install kubectl
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
chmod +x ./kubectl
sudo cp ./kubectl /usr/local/bin/kubectl
sudo kubectl version --client
sudo kubectl --help
实现 kubectl 的命令补全功能
# make sure bash-completion is installed
sudo apt-get install bash-completion
# make sure bash-completion is sourced in ~/.bashrc (root and other users)
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
# or
if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
. /etc/bash_completion
fi
# make sure kubectl completion is sourced in ~/.bashrc (root and other users)
echo 'source <(kubectl completion bash)' >>~/.bashrc
# generate kubectl completion file
sudo bash -c "./kubectl completion bash >/etc/bash_completion.d/kubectl"
kubectl 是 Go 语言实现的
Install a Hypervisor
这是可选项,通过安装 KVM 或 VirtualBox 等工具,Minikube 可以创建 VM 并在上面安装运行程序,如果不安装 Hypervisor 那 Minikube 就在本机上安装运行程序
Install Minikube
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
chmod +x minikube
sudo cp ./minikube /usr/local/bin/minikube
sudo minikube start --driver=<driver_name>
如果没有安装 Hypervisor,需要将 driver 指定为 none
sudo minikube start --driver=none
通过 none driver 启动,结果报错
😄 Ubuntu 16.04 (vbox/amd64) 上的 minikube v1.11.0
✨ 根据用户配置使用 none 驱动程序
💣 Sorry, Kubernetes 1.18.3 requires conntrack to be installed in root's path
提示要安装 conntrack
sudo apt-get install conntrack
重新启动 Minikube
😄 Ubuntu 16.04 (vbox/amd64) 上的 minikube v1.11.0
✨ 根据用户配置使用 none 驱动程序
👍 Starting control plane node minikube in cluster minikube
🤹 Running on localhost (CPUs=4, Memory=7976MB, Disk=18014MB) ...
ℹ️ OS release is Ubuntu 16.04.6 LTS
🐳 正在 Docker 19.03.8 中准备 Kubernetes v1.18.3…
❗ This bare metal machine is having trouble accessing https://k8s.gcr.io
💡 To pull new external images, you may need to configure a proxy: https://minikube.sigs.k8s.io/docs/reference/networking/proxy/
> kubeadm.sha256: 65 B / 65 B [--------------------------] 100.00% ? p/s 0s
> kubectl.sha256: 65 B / 65 B [--------------------------] 100.00% ? p/s 0s
> kubelet.sha256: 65 B / 65 B [--------------------------] 100.00% ? p/s 0s
> kubectl: 41.99 MiB / 41.99 MiB [----------------] 100.00% 6.79 MiB p/s 6s
> kubeadm: 37.97 MiB / 37.97 MiB [----------------] 100.00% 4.44 MiB p/s 9s
> kubelet: 108.04 MiB / 108.04 MiB [-------------] 100.00% 6.35 MiB p/s 18s
💥 initialization failed, will try again: run: /bin/bash -c "sudo env PATH=/var/lib/minikube/binaries/v1.18.3:$PATH kubeadm init --config /var/tmp/minikube/kubeadm.yaml --ignore-preflight-errors=DirAvailable--etc-kubernetes-manifests,DirAvailable--var-lib-minikube,DirAvailable--var-lib-minikube-etcd,FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml,FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml,FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml,FileAvailable--etc-kubernetes-manifests-etcd.yaml,Port-10250,Swap": exit status 1
stdout:
[init] Using Kubernetes version: v1.18.3
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
stderr:
W0609 16:35:49.251770 29943 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
[WARNING Swap]: running with swap on is not supported. Please disable swap
[WARNING FileExisting-ebtables]: ebtables not found in system path
[WARNING FileExisting-socat]: socat not found in system path
[WARNING Service-Kubelet]: kubelet service is not enabled, please run 'systemctl enable kubelet.service'
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-apiserver:v1.18.3: output: Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
, error: exit status 1
[ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-controller-manager:v1.18.3: output: Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
, error: exit status 1
[ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-scheduler:v1.18.3: output: Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
, error: exit status 1
[ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-proxy:v1.18.3: output: Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
, error: exit status 1
[ERROR ImagePull]: failed to pull image k8s.gcr.io/pause:3.2: output: Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
, error: exit status 1
[ERROR ImagePull]: failed to pull image k8s.gcr.io/etcd:3.4.3-0: output: Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
, error: exit status 1
[ERROR ImagePull]: failed to pull image k8s.gcr.io/coredns:1.6.7: output: Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
, error: exit status 1
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher
还是报错,无法访问 https://k8s.gcr.io,使用国内的源
sudo minikube start --driver=none --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers
成功了
😄 Ubuntu 16.04 (vbox/amd64) 上的 minikube v1.11.0
✨ 根据现有的配置文件使用 none 驱动程序
👍 Starting control plane node minikube in cluster minikube
🔄 Restarting existing none bare metal machine for "minikube" ...
ℹ️ OS release is Ubuntu 16.04.6 LTS
🐳 正在 Docker 19.03.8 中准备 Kubernetes v1.18.3…
🤹 开始配置本地主机环境...
❗ The 'none' driver is designed for experts who need to integrate with an existing VM
💡 Most users should use the newer 'docker' driver instead, which does not require root!
📘 For more information, see: https://minikube.sigs.k8s.io/docs/reference/drivers/none/
❗ kubectl 和 minikube 配置将存储在 /home/lin 中
❗ 如需以您自己的用户身份使用 kubectl 或 minikube 命令,您可能需要重新定位该命令。例如,如需覆盖您的自定义设置,请运行:
▪ sudo mv /home/lin/.kube /home/lin/.minikube $HOME
▪ sudo chown -R $USER $HOME/.kube $HOME/.minikube
💡 此操作还可通过设置环境变量 CHANGE_MINIKUBE_NONE_USER=true 自动完成
🔎 Verifying Kubernetes components...
🌟 Enabled addons: default-storageclass, storage-provisioner
🏄 完成!kubectl 已经配置至 "minikube"
💡 为获得最佳结果,请安装 kubectl:https://kubernetes.io/docs/tasks/tools/install-kubectl/
Minikube 默认至少要双核,如果只有单核,需要指定配置
sudo minikube start --driver=none \
--extra-config=kubeadm.ignore-preflight-errors=NumCPU \
--force --cpus 1 \
--image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers
检查 Minikube 的状态
sudo minikube status
正常返回如下
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
停止集群
sudo minikube stop
删除集群
sudo minikube delete
验证 kubectl
sudo kubectl version --client
sudo kubectl cluster-info
返回
lin@lin-VirtualBox:~/K8S$ sudo kubectl version --client
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.3", GitCommit:"2e7996e3e2712684bc73f0dec0200d64eec7fe40", GitTreeState:"clean", BuildDate:"2020-05-20T12:52:00Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
lin@lin-VirtualBox:~/K8S$
lin@lin-VirtualBox:~/K8S$
lin@lin-VirtualBox:~/K8S$ sudo kubectl cluster-info
Kubernetes master is running at https://xxx.xxx.xxx.xxx:8443
KubeDNS is running at https://xxx.xxx.xxx.xxx:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Minikube 是 Go 语言实现的
例子:echoserver
echoserver 镜像是一个简单的 HTTP 服务器,将请求的 body 携待的参数返回
这里没有定义 manifest 文件,而是直接指定 image 做 deploy,这一步会启动一个 deployment 和对应的 pod
sudo kubectl create deployment hello-minikube \
--image=registry.cn-hangzhou.aliyuncs.com/google_containers/echoserver:1.10
暴露端口,这一步会启动一个 service
sudo kubectl expose deployment hello-minikube --type=NodePort --port=8080
查看 pod 的状态
sudo kubectl get pod
sudo kubectl get pods
sudo kubectl get pods -o wide
get pod 的返回
NAME READY STATUS RESTARTS AGE
hello-minikube-7df785b6bb-v2phl 1/1 Running 0 5m51s
查看 pod 的信息
sudo kubectl describe pod hello-minikube
describe pod 的返回
Name: hello-minikube-7df785b6bb-mw6kv
Namespace: default
Priority: 0
Node: lin-virtualbox/100.98.137.196
Start Time: Wed, 10 Jun 2020 16:30:18 +0800
Labels: app=hello-minikube
pod-template-hash=7df785b6bb
Annotations: <none>
Status: Running
IP: 172.17.0.6
IPs:
IP: 172.17.0.6
Controlled By: ReplicaSet/hello-minikube-7df785b6bb
Containers:
echoserver:
Container ID: docker://ca6c7070ef7afc260f6fe6538da49e91bc60ba914b623d6080b03bd2886343b3
Image: registry.cn-hangzhou.aliyuncs.com/google_containers/echoserver:1.10
Image ID: docker-pullable://registry.cn-hangzhou.aliyuncs.com/google_containers/echoserver@sha256:56bec57144bd3610abd4a1637465ff491dd78a5e2ae523161569fa02cfe679a8
Port: <none>
Host Port: <none>
State: Running
Started: Wed, 10 Jun 2020 16:30:21 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-znf6q (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-znf6q:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-znf6q
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events: <none>
查看 deployment 的状态
sudo kubectl get deployment
get deployment 的返回
NAME READY UP-TO-DATE AVAILABLE AGE
hello-minikube 1/1 1 1 80m
查看 service 的状态
sudo minikube service hello-minikube --url
# or
sudo minikube service hello-minikube
返回
http://100.98.137.196:31526
# or
|-----------|----------------|-------------|-----------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|----------------|-------------|-----------------------------|
| default | hello-minikube | 8080 | http://100.98.137.196:31526 |
|-----------|----------------|-------------|-----------------------------|
向 echoserver 发送请求
curl -X POST -d '{"abc":123}' http://100.98.137.196:31526/api/v1/hello
返回
Hostname: hello-minikube-7df785b6bb-v2phl
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.3 - lua: 10008
Request Information:
client_address=172.17.0.1
method=POST
real path=/api/v1/hello
query=
request_version=1.1
request_scheme=http
request_uri=http://100.98.137.196:8080/api/v1/hello
Request Headers:
accept=*/*
content-length=11
content-type=application/x-www-form-urlencoded
host=100.98.137.196:31384
user-agent=curl/7.47.0
Request Body:
{"abc":123}
删除 service
sudo kubectl delete services hello-minikube
删除 service 后 Pod 不受影响还在 running
删除 deployment 后 Pod 才会被删除
sudo kubectl delete deployment hello-minikube
启动 Dashboard
sudo minikube dashboard
返回
🔌 正在开启 dashboard ...
🤔 正在验证 dashboard 运行情况 ...
🚀 Launching proxy ...
🤔 正在验证 proxy 运行状况 ...
http://127.0.0.1:42155/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/
登陆 URL 可以看到
命名空间选择 "全部 namespaces",可以看到,K8S 的组件如 apiserver、controller、etcd、scheduler 等等也是容器化的
实际上这些镜像和启动的容器通过 docker 命令也可以看到
lin@lin-VirtualBox:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy v1.18.3 3439b7546f29 2 weeks ago 117MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler v1.18.3 76216c34ed0c 2 weeks ago 95.3MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver v1.18.3 7e28efa976bd 2 weeks ago 173MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager v1.18.3 da26705ccb4b 2 weeks ago 162MB
kubernetesui/dashboard v2.0.0 8b32422733b3 7 weeks ago 222MB
registry.cn-hangzhou.aliyuncs.com/google_containers/pause 3.2 80d28bedfe5d 3 months ago 683kB
registry.cn-hangzhou.aliyuncs.com/google_containers/coredns 1.6.7 67da37a9a360 4 months ago 43.8MB
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd 3.4.3-0 303ce5db0e90 7 months ago 288MB
kubernetesui/metrics-scraper v1.0.2 3b08661dc379 7 months ago 40.1MB
registry.cn-hangzhou.aliyuncs.com/google_containers/echoserver 1.10 365ec60129c5 2 years ago 95.4MB
registry.cn-hangzhou.aliyuncs.com/google_containers/storage-provisioner v1.8.1 4689081edb10 2 years ago 80.8MB
docker ps -a
可以用 docker 命令操作这些 K8S 启动的容器,比如
docker exec
docker logs
kubectl 也有相应的命令做操作,比如
kubectl exec
kubectl logs
另外绕过 K8S 部署的容器 K8S 无法管理
Wordaround if coredns fail
从 Dashboard 可以看到,有个 coredns 的服务出错了,有的服务会受到影响,比如后面要讲的 Flink on K8S
通过 kubectl get pod 查看状态
lin@lin-VirtualBox:~/K8S$ sudo kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-546565776c-5fq7p 0/1 CrashLoopBackOff 3 7h21m
coredns-546565776c-zx72j 0/1 CrashLoopBackOff 3 7h21m
etcd-lin-virtualbox 1/1 Running 0 7h21m
kube-apiserver-lin-virtualbox 1/1 Running 0 7h21m
kube-controller-manager-lin-virtualbox 1/1 Running 0 7h21m
kube-proxy-rgsgg 1/1 Running 0 7h21m
kube-scheduler-lin-virtualbox 1/1 Running 0 7h21m
storage-provisioner 1/1 Running 0 7h21m
通过 kubectl logs 查看日志
lin@lin-VirtualBox:~/K8S$ sudo kubectl logs -n kube-system coredns-546565776c-5fq7p
.:53
[INFO] plugin/reload: Running configuration MD5 = 4e235fcc3696966e76816bcd9034ebc7
CoreDNS-1.6.7
linux/amd64, go1.13.6, da7f65b
[FATAL] plugin/loop: Loop (127.0.0.1:58992 -> :53) detected for zone ".", see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO 5310754532638830744.3332451342029566297."
临时方案如下
# 编辑 coredns 的 ConfigMap,有一行 loop,将其删除
sudo kubectl edit cm coredns -n kube-system
# 重启服务
sudo kubectl delete pod coredns-546565776c-5fq7p -n kube-system
sudo kubectl delete pod coredns-546565776c-zx72j -n kube-system
重启后可以看到 coredns 变成 running 了
例子:Flink on K8S
定义 manifest 文件
https://ci.apache.org/projects/flink/flink-docs-release-1.10/ops/deployment/kubernetes.html
flink-configuration-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: flink-config
labels:
app: flink
data:
flink-conf.yaml: |+
jobmanager.rpc.address: flink-jobmanager
taskmanager.numberOfTaskSlots: 1
blob.server.port: 6124
jobmanager.rpc.port: 6123
taskmanager.rpc.port: 6122
jobmanager.heap.size: 1024m
taskmanager.memory.process.size: 1024m
log4j.properties: |+
log4j.rootLogger=INFO, file
log4j.logger.akka=INFO
log4j.logger.org.apache.kafka=INFO
log4j.logger.org.apache.hadoop=INFO
log4j.logger.org.apache.zookeeper=INFO
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.file=${log.file}
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
log4j.logger.org.apache.flink.shaded.akka.org.jboss.netty.channel.DefaultChannelPipeline=ERROR, file
jobmanager-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: flink-jobmanager
spec:
replicas: 1
selector:
matchLabels:
app: flink
component: jobmanager
template:
metadata:
labels:
app: flink
component: jobmanager
spec:
containers:
- name: jobmanager
image: flink:latest
workingDir: /opt/flink
command: ["/bin/bash", "-c", "$FLINK_HOME/bin/jobmanager.sh start;\
while :;
do
if [[ -f $(find log -name '*jobmanager*.log' -print -quit) ]];
then tail -f -n +1 log/*jobmanager*.log;
fi;
done"]
ports:
- containerPort: 6123
name: rpc
- containerPort: 6124
name: blob
- containerPort: 8081
name: ui
livenessProbe:
tcpSocket:
port: 6123
initialDelaySeconds: 30
periodSeconds: 60
volumeMounts:
- name: flink-config-volume
mountPath: /opt/flink/conf
securityContext:
runAsUser: 9999 # refers to user _flink_ from official flink image, change if necessary
volumes:
- name: flink-config-volume
configMap:
name: flink-config
items:
- key: flink-conf.yaml
path: flink-conf.yaml
- key: log4j.properties
path: log4j.properties
taskmanager-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: flink-taskmanager
spec:
replicas: 2
selector:
matchLabels:
app: flink
component: taskmanager
template:
metadata:
labels:
app: flink
component: taskmanager
spec:
containers:
- name: taskmanager
image: flink:latest
workingDir: /opt/flink
command: ["/bin/bash", "-c", "$FLINK_HOME/bin/taskmanager.sh start; \
while :;
do
if [[ -f $(find log -name '*taskmanager*.log' -print -quit) ]];
then tail -f -n +1 log/*taskmanager*.log;
fi;
done"]
ports:
- containerPort: 6122
name: rpc
livenessProbe:
tcpSocket:
port: 6122
initialDelaySeconds: 30
periodSeconds: 60
volumeMounts:
- name: flink-config-volume
mountPath: /opt/flink/conf/
securityContext:
runAsUser: 9999 # refers to user _flink_ from official flink image, change if necessary
volumes:
- name: flink-config-volume
configMap:
name: flink-config
items:
- key: flink-conf.yaml
path: flink-conf.yaml
- key: log4j.properties
path: log4j.properties
jobmanager-service.yaml
apiVersion: v1
kind: Service
metadata:
name: flink-jobmanager
spec:
type: ClusterIP
ports:
- name: rpc
port: 6123
- name: blob
port: 6124
- name: ui
port: 8081
selector:
app: flink
component: jobmanager
jobmanager-rest-service.yaml. Optional service, that exposes the jobmanager rest port as public Kubernetes node’s port.
apiVersion: v1
kind: Service
metadata:
name: flink-jobmanager-rest
spec:
type: NodePort
ports:
- name: rest
port: 8081
targetPort: 8081
selector:
app: flink
component: jobmanager
通过 manifest 文件启动,注意有先后顺序
sudo kubectl create -f flink-configuration-configmap.yaml
sudo kubectl create -f jobmanager-service.yaml
sudo kubectl create -f jobmanager-deployment.yaml
sudo kubectl create -f taskmanager-deployment.yaml
查看配置的 ConfigMap
lin@lin-VirtualBox:~/K8S$ sudo kubectl get configmap
NAME DATA AGE
flink-config 2 4h28m
查看启动的 Pod
lin@lin-VirtualBox:~/K8S$ sudo kubectl get pods
NAME READY STATUS RESTARTS AGE
flink-jobmanager-574676d5d5-g75gh 1/1 Running 0 5m24s
flink-taskmanager-5bdb4857bc-vvn2j 1/1 Running 0 5m23s
flink-taskmanager-5bdb4857bc-wn5c2 1/1 Running 0 5m23s
hello-minikube-7df785b6bb-j9g6g 1/1 Running 0 55m
查看启动的 Deployment
lin@lin-VirtualBox:~/K8S$ sudo kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
flink-jobmanager 1/1 1 1 4h28m
flink-taskmanager 1/2 2 1 4h28m
hello-minikube 1/1 1 1 5h18m
查看启动的 Service
lin@lin-VirtualBox:~/K8S$ sudo kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
flink-jobmanager ClusterIP 10.96.132.16 <none> 6123/TCP,6124/TCP,8081/TCP 4h28m
hello-minikube NodePort 10.104.137.240 <none> 8080:30041/TCP 5h18m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5h25m
登陆 Flink UI 以及提交 Flink Job 的几种方式
https://ci.apache.org/projects/flink/flink-docs-release-1.10/ops/deployment/kubernetes.html#deploy-flink-session-cluster-on-kubernetes
- proxy 方式
命令
kubectl proxy
登陆 URL
http://localhost:8001/api/v1/namespaces/default/services/flink-jobmanager:ui/proxy
(这种方式没讲到怎么 run job)
- NodePort service 方式
命令
sudo kubectl create -f jobmanager-rest-service.yaml
sudo kubectl get svc flink-jobmanager-rest
lin@lin-VirtualBox:~/K8S$ sudo kubectl get svc flink-jobmanager-rest
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
flink-jobmanager-rest NodePort 10.96.150.145 <none> 8081:32598/TCP 12s
登陆 URL
http://10.96.150.145:8081
提交 Job
./bin/flink run -m 10.96.150.145:8081 ./examples/streaming/WordCount.jar
在 UI 上可以看到提交的 Job
- port-forward
宿主机安装 socat
sudo apt-get install socat
命令
sudo kubectl port-forward flink-jobmanager-574676d5d5-xd9kx 8081:8081
登陆 URL
http://localhost:8081
提交 Job
./bin/flink run -m localhost:8081 ./examples/streaming/WordCount.jar
在 UI 上可以看到提交的 Job
删除 Flink
sudo kubectl delete -f jobmanager-deployment.yaml
sudo kubectl delete -f taskmanager-deployment.yaml
sudo kubectl delete -f jobmanager-service.yaml
sudo kubectl delete -f flink-configuration-configmap.yaml