本地快速装一个微型的kubernetes环境, 翻墙的苦谁能懂?

mac 本地安装minikube环境

环境需求:

  • kubectl 本地做命令行控制用, 所有的命令操作都是通过它
  • vittualBox v5.1 + 更新到最新版本就对了
  • minikube 在本地搭建测试环境

翻墙有困难的可以参考一下这个 https://yq.aliyun.com/articles/221687

安装 kubectl

1
brew install kubectl

下载最新 minikube 不建议使用brew安装, 首先版本不会是最新, 再者会出现莫名其妙的问题

1
2
3
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 && \
  chmod +x minikube && \
  sudo mv minikube /usr/local/bin/

默认 start 时运行的virtualBox 去官网下个最新的就行

启动, 最好把docker镜像指定到国内

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
~ minikube start --registry-mirror=https://registry.docker-cn.com
😄  minikube v1.0.1 on darwin (amd64)
💿  Downloading Minikube ISO ...
 142.88 MB / 142.88 MB [============================================] 100.00% 0s
🤹  Downloading Kubernetes v1.14.1 images in the background ...
🔥  Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...
📶  "minikube" IP address is 192.168.99.103
🐳  Configuring Docker as the container runtime ...
🐳  Version of container runtime is 18.06.3-ce
Waiting for image downloads to complete ...
Preparing Kubernetes environment ...
💾  Downloading kubeadm v1.14.1
💾  Downloading kubelet v1.14.1
🚜  Pulling images required by Kubernetes v1.14.1 ...
🚀  Launching Kubernetes v1.14.1 using kubeadm ...
Waiting for pods: apiserver proxy etcd scheduler controller dns
🔑  Configuring cluster permissions ...
🤔  Verifying component health .....
💗  kubectl is now configured to use "minikube"
🏄  Done! Thank you for using minikube!
~ kubectl cluster-info
Kubernetes master is running at https://192.168.99.103:8443
KubeDNS is running at https://192.168.99.103:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

如果Minikube ISO存在墙的问题, 就把iso下载后放到 ~/.minikube/cache/iso/

这时Mac上的docker不能用docker for Mac提供的了, 而是宿主机里面的docker, 切换命令为:

1
eval $(minikube docker-env)

撤销更改

1
eval $(minikube docker-env -u)

加载后台控制面板, 稍等一会, 自动打卡后台界面

1
minikube dashboard

部署第一个应用

命令行部署
创建node.js 应用

创建文件 server.js

1
2
3
4
5
6
7
8
9
var http = require('http');

var handleRequest = function(request, response) {
  console.log('Received request for URL: ' + request.url);
  response.writeHead(200);
  response.end('Hello World! V1');
};
var www = http.createServer(handleRequest);
www.listen(3000);

运行

1
node server.js   // 访问地址  http://localhost:3000
创建docker镜像
1
2
3
4
5
6
FROM node:8.10.0

EXPOSE 3000

COPY server.js .
CMD ["node", "server.js"]

构建镜像

1
docker build -t hello-node:v1 .

如果出现Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? 说明你忘了执行 eval $(minikube docker-env) kube用的 docker 和你本地用的 docker 是两个位置, kube的在虚拟机里运行

创建 deployment

有了镜像就具备创建pod的条件, 通常来说不用直接创建 pod, 而是创建 deployment 或者 replication controller, 由他们来负责管理服务的运行, 规模缩放, 自动重启等等这些操作, 就单个pod来说是可以随时被销毁的, 不能作为稳定服务的保证

1
2
3
kubectl run hello-node --image=hello-node:v1 --port=3000
kubectl create deployment hello-node --image=hello-node:v1

查看当前deployment

1
2
3
kubectl get deployments 
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
hello-node     1/1     1            1           8m8s

ready 1/1 说明已经准备就绪了

查看 pod

1
2
3
hellonode git:(master)kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
hello-node-5c58cb6dd4-h65fx     1/1     Running   0          8m40s

从这两条信息就能看出来, 每个pod都是带随机字符串的, 并不打算给人去操作, 我们主要专注在deploymentservice 的搭建

查看 deployment 描述

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
➜ kubectl describe deployments/hello-node

Name:                   hello-node
Namespace:              default
CreationTimestamp:      Mon, 13 May 2019 14:17:03 +0800
Labels:                 run=hello-node
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               run=hello-node
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  run=hello-node
  Containers:
   hello-node:
    Image:        hello-node:v1
    Port:         3000/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   hello-node-5c58cb6dd4 (1/1 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  11m   deployment-controller  Scaled up replica set hello-node-5c58cb6dd4 to 1

这里是对deployment的概览, Pod Template: 下就是每个pods的配置, 之后对部署的扩容都是基于这个去复制

到目前为止我们创建了deployment 而且也自动生成pod了, 可是服务并不能被访问到, 为什么? 因为端口没有对外暴露出来, 所以有了下一步

创建service

service 就是用来对我暴露服务的东西, 所有的 pod 都是在内网通信, 外部访问就得让 service 这层代理去转发过去, --type=LoadBalancer 就是指定转发为负载均衡模式, kubectl create service -h 查看更多, 这里不细讲

创建service

1
2
3
kubectl expose deployment hello-node --type=LoadBalancer
kubectl expose deployment hello-node --type=LoadBalancer --port=3000 // 这里指定端口

查看

1
2
3
4
kubectl get service                                     
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-node   LoadBalancer   10.111.18.151   <pending>     3000:31349/TCP   3s
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP          3d

详细信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
kubectl describe services hello-node 
Name:                     hello-node
Namespace:                default
Labels:                   run=hello-node
Annotations:              <none>
Selector:                 run=hello-node
Type:                     LoadBalancer
IP:                       10.111.18.151
Port:                     <unset>  3000/TCP
TargetPort:               3000/TCP
NodePort:                 <unset>  31349/TCP
Endpoints:                172.17.0.7:3000
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

NodePort 就是绑定在节点的那个端口上, 直接访问节点ip就行, 也可以用minikube命令 minikube service hello-node 自动帮你打开本地地址

扩展示例

线上肯定是有这种动态扩容的情况, 而且多实例之间滚动升级也不会停止服务

1
2
3
4
5
6
7
8
kubectl scale deployments/hello-node --replicas=4
deployment.extensions/hello-node scaled
hellonode git:(master)kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
hello-node-5c58cb6dd4-d2qq9   1/1     Running   0          18s
hello-node-5c58cb6dd4-h65fx   1/1     Running   0          51m
hello-node-5c58cb6dd4-jlzjw   1/1     Running   0          18s
hello-node-5c58cb6dd4-vmx4f   1/1     Running   0          18s
更新应用

重新构建一个node的镜像 service.js

1
2
3
4
5
6
7
8
9
var http = require('http');

var handleRequest = function(request, response) {
  console.log('Received request for URL: ' + request.url);
  response.writeHead(200);
  response.end('Hello World! V2');
};
var www = http.createServer(handleRequest);
www.listen(3000);
1
docker build -t hello-node:v2 .

设置 deployment 使用新镜像

1
kubectl set image deployment/hello-node hello-node=hello-node:v2

查看每个pod的具体情况

1
kubectl describe pods

再访问刚才的地址就能看到改变了

清除资源
1
2
kubectl delete service hello-node
kubectl delete deployments hello-node

经过上面一套操作下来, 应该也对k8s有了一个大致的印象了, 毕竟光看实践才是检验真理的唯一标准, 但是如果部署一个服务这样一个命令一个命令的敲是很要命的, 而且服务器这玩意, 轻易不会动, 时间一长就容易忘, 因此用配置文件去启动更加合理

通过 yaml 启动

如下: test-service.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: v1
kind: Service
metadata: 
  name: test-service
  labels:
    version: v2
    run: hello-node
    app: test-service
spec:
  type: LoadBalancer
  ports:
  - port: 3001
    targetPort: 3000
    protocol: TCP
  selector:
    app: test-service
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-service
  labels:
    app: test-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-service
  template:
    metadata:
      labels:
        app: test-service
    spec:
      containers:
      - name: node-pod
        image: hello-node:v2
        imagePullPolicy: IfNotPresent
        ports: 
        - containerPort: 3000

执行

1
2
kubectl create -f test-service.yaml
minikube service test-service

这样通过配置文件就能启动了, 配置文件里里的字段后续我们再详细的讲一下

删除 kubectl delete -f test-service.yaml

代码地址

相关资料