一、部署nginx应用到k8s上
1.创建一个部署:kubectl create deployment nginx --image=nginx
2.查看部署:kubectl get deployments
3.创建一个服务:kubectl create service nodeport nginx --tcp 80:80
4.查看服务:kubectl get svc
5. 查看是否部署成功:curl localhost:30376
二、使用yaml文件部署应用到k8s上
1.创建一个nodejs应用程序,创建一个文件夹kube-demo, 接着创建一个server.js文件:
var http = require('http');
var handleRequest = function(request, response) {
console.log('Received request for URL: ' + request.url);
response.writeHead(200);
response.end('Hello World!');
};
var www = http.createServer(handleRequest);
www.listen(8081);
运行应用:node server.js,打开浏览器访问http://localhost:8081, 可以看到我们的小应用程序可以正常运行,使用按Ctrl+C停止正在运行的Node.js服务器,将应用程序打包成Docker镜像并Push到Docker hub上去,接下来我们将此应用程序打包成Docker 镜像,这里使用Dockerfile来进行打包,如果看到这里你不太明白,那么你需要先学习一下Docker. Dockerfile的内容如下:
FROM node:8.11.2
WORKDIR app
COPY . .
EXPOSE 8081
ENTRYPOINT [ "node","server.js" ]
Dockerfile创建好后,执行如下命令:
docker build -t wucong60/kube-node-demo1:v1 .
运行docker images,可以看到镜像打包成功了,执行docker login --username <你在dockerhub注册的账号> 再输入密码登录到docker hub,再将刚打包好的镜像push上去:
root@kube-dev:/home/cong/Desktop/NodeDemo1# docker login --username wucong60
Password:
Login Succeeded
root@kube-dev:/home/cong/Desktop/NodeDemo1# docker push wucong60/kube-node-demo1:v1
The push refers to a repository [docker.io/wucong60/kube-node-demo1]
3f17035e6c72: xxxxx
.....
v1: digest: sha256:009219456e793f3b53b777915247c71635b9c5bec6e70de6ab1f08664d056917 size: 2420
这时,所有人都可以从docker hub(公有镜像库)中拉取此镜像了。使用yaml文件创建Deployment, 创建一个名为deployment.yaml的yaml文件,内容如下:
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: kube-node
spec:
replicas: 2
template:
metadata:
labels:
app: web
spec:
containers:
- name: kube-node-demo-instance
image: wucong60/kube-node-demo1:v1
ports:
- containerPort: 8081
执行kubectl create -f deployment.yaml命令,创建一个deployment:
root@kube-master:/home/cong/Desktop/NodeDemo1# kubectl create -f deployment.yaml
deployment.extensions/kube-node created
root@kube-master:/home/cong/Desktop/NodeDemo1# kubectl get pods
NAME READY STATUS RESTARTS AGE
kube-node-59bf664cbf-2qzgd 0/1 ImagePullBackOff 0 9s
kube-node-59bf664cbf-p6wtg 0/1 ImagePullBackOff 0 9s
结果发现Pods的状态为ImagePullBackOff, 最终发现是,因为k8s不能够拉取私有仓库的镜像,通过执行下列命令可以查看具体的Pod信息,其中里面的Events下面显示了创建Pod的详细过程:
kubectl describe pods/kube-node-59bf664cbf-2qzgd
参考Kubernetes配置secret拉取私有仓库镜像的官方文档后(点击这里查看),执行如下命令
root@kube-master:/home/cong/Desktop/NodeDemo1# kubectl create secret docker-registry myregistrykey --docker-server=https://index.docker.io/v1/ --docker-username=wucong60 [email protected]
root@kube-master:/home/cong/Desktop/NodeDemo1# kubectl get secrets
NAME TYPE DATA AGE
default-token-2lvth kubernetes.io/service-account-token 3 4d
myregistrykey kubernetes.io/dockerconfigjson 1 4h
这样我们就创建好了secret,然后再将这个secret加到yaml文件中,修改后的deployment.yaml文件如下:
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: kube-node
spec:
replicas: 2
template:
metadata:
labels:
app: web
spec:
containers:
- name: kube-node-demo-instance
image: kube-node-demo1
ports:
- containerPort: 8081
imagePullSecrets:
- name: myregistrykey
删除之前的deployment并重新创建新的deployment(另一方法是 :直接编辑此deployment,命令是:kubectl edit deployments/kube-node,编辑完后就立即生效了,所有pods会重新生成),命令如下:
kubectl delete deployments/kube-node
kubectl create -f deployment.yaml
最终可以看到我们的应用程序被部署上去了:
root@kube-master:/home/cong/Desktop/NodeDemo1# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
kube-node-7bd98cf84d-c6q6h 1/1 Running 0 3m 10.244.2.66 kube-slave-1
kube-node-7bd98cf84d-fbjwz 1/1 Running 0 3m 10.244.1.36 kube-slave-3
执行下列命令,来验证部署上去的应用程序是否好用,我们尝试访问第一个IP+8081端口,正常显示Hello World!
root@kube-master:/home/cong/Desktop/NodeDemo1# curl 10.244.2.66:8081
Hello World!
2.Pod是有生命周期的,使用凡人皆有一死来描述pod很贴切,当一个工作节点(node)销毁时,节点上运行的pods也会被销毁, ReplicationController会动态地在其他节点上创建Pod来保持应用程序的运行,每一个Pod都有一个独立的IP地址,甚至是同一个节点上的Pod,可以看出Pod的IP是动态的,它随Pod的创建而创建,随Pod的销毁而消失,这就引出一个问题:如果由一组Pods组合而成的集群来提供服务,那如何访问这些Pods呢?Kubenetes的Service就是用来解决这个问题的。一个Service可以看作一组提供相同服务的Pods的对外访问接口,Service作用于哪些Pods是通过label selector来定义的,这些Pods能被Service访问,Pod之间的发现和路由(如应用中的前端和后端组件)由Kubernetes Service处理。
Service有四种type: ClusterIP(默认)、NodePort、LoadBalancer、ExternalName. 其中NodePort和LoadBalancer两类型的Services可以对外提供服务。
使用yaml文件创建Service(NodePort), 这里使用yaml文件来创建NodePort类型的Service,service.yaml文件内容如下:
---
apiVersion: v1
kind: Service
metadata:
name: kube-node-service
labels:
name: kube-node-service
spec:
type: NodePort #这里代表是NodePort类型的
ports:
- port: 80 #这里的端口和clusterIP(10.97.114.36)对应,即10.97.114.36:80,供内部访问。
targetPort: 8081 #端口一定要和container暴露出来的端口对应,nodejs暴露出来的端口是8081,所以这里也应是8081
protocol: TCP
nodePort: 32143 # 所有的节点都会开放此端口,此端口供外部调用。
selector:
app: web #这里选择器一定要选择容器的标签,之前写name:kube-node是错的。
执行命令创建一个service,并列出所有的services:
root@kube-master:/home/cong/Desktop/NodeDemo1# kubectl create -f service.yaml
service/kube-node-service created
root@kube-master:/home/cong/Desktop/NodeDemo1# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-node-service NodePort 10.97.114.36 80:32143/TCP 7s
kubernetes ClusterIP 10.96.0.1 443/TCP 7d
我们来验证一下创建的service是否正确,执行如下命令
root@kube-master:/home/cong/Desktop/NodeDemo1# curl localhost:32143
Hello World!
# 由于定义的port是80,所以直接访问clusterIP
root@kube-master:/home/cong/Desktop/NodeDemo1# curl 10.97.114.36
Hello World!
首先外部使用load balancer访问我们的两个slave节点(192.168.29.141:32143) 和 (192.168.29.139:32143),接着它会访问Service,即ClusterIP(10.97.114.36:80), Service再通过load balancer访问到某一个pod(端口8081)里的container(端口8081)。 这里第二个load balancer是由kube-proxy来负责的,官方的描述是:kube-proxy负责为service提供cluster内部的服务发现和负载均衡。实际上,我们还另一种创建service的方式,更快更便捷,即使用expose命令来创建service,如下:
root@kube-master:/home/cong# kubectl expose deployment kube-node --type=NodePort
service/kube-node exposed
root@kube-master:/home/cong# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-node NodePort 10.107.247.158 8081:31195/TCP 10s
kube-node-service NodePort 10.97.114.36 80:32143/TCP 1d
kubernetes ClusterIP 10.96.0.1 443/TCP 8d
nginx NodePort 10.99.22.64 80:32322/TCP 2d
root@kube-master:/home/cong# curl localhost:31195
Hello World!
root@kube-master:/home/cong# curl 10.107.247.158:8081
Hello World!
root@kube-master:/home/cong# kubectl describe services/kube-node
Name: kube-node
Namespace: default
Labels: app=web
Annotations:
Selector: app=web
Type: NodePort
IP: 10.107.247.158
Port: 8081/TCP
TargetPort: 8081/TCP
NodePort: 31195/TCP
Endpoints: 10.244.1.71:8081,10.244.2.81:8081 #这里podIp+端口号就是endpoint
Session Affinity: None
External Traffic Policy: Cluster
Events:
root@kube-master:/home/cong# kubectl describe services/kube-node-service
Name: kube-node-service
Namespace: default
Labels: name=kube-node-service
Annotations:
Selector: app=web
Type: NodePort
IP: 10.97.114.36
Port: 80/TCP
TargetPort: 8081/TCP
NodePort: 32143/TCP
Endpoints: 10.244.1.71:8081,10.244.2.81:8081 #虽然暴露了两个service,但endpoint是一样滴。
Session Affinity: None
External Traffic Policy: Cluster
Events:
可以看出,expose命令这里并没有指定clusterIP,说明它是K8S系统中的虚拟IP地址,由系统动态分配。Pod的IP地址是由flannel插件来分配的,而不再由Docker Daemon根据docker0网桥的IP地址进行分配。可以在任意节点上输入ifconfig可以看到。使用yaml文件创建Service(LoadBalancer), 这里我们继续expose命令创建loadBalancer类型的service,命令如下:
service "kube-node" deleted
root@kube-master:/home/cong# kubectl expose deployment kube-node --type=LoadBalancer
service/kube-node exposed
root@kube-master:/home/cong# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-node LoadBalancer 10.99.201.195 8081:31585/TCP 10s
kube-node-service NodePort 10.97.114.36 80:32143/TCP 1d
kubernetes ClusterIP 10.96.0.1 443/TCP 8d
nginx NodePort 10.99.22.64 80:32322/TCP 2d
root@kube-master:/home/cong# curl localhost:31585
Hello World!
root@kube-master:/home/cong# curl 10.99.201.195:8081
Hello World!
root@kube-master:/home/cong# kubectl describe services/kube-node
Name: kube-node
Namespace: default
Labels: app=web
Annotations:
Selector: app=web
Type: LoadBalancer
IP: 10.99.201.195
Port: 8081/TCP
TargetPort: 8081/TCP
NodePort: 31585/TCP
Endpoints: 10.244.1.71:8081,10.244.2.81:8081
Session Affinity: None
External Traffic Policy: Cluster
Events:
当然我们也可以使用yaml文件来创建,service-lb.yaml文件如下:
---
apiVersion: v1
kind: Service
metadata:
name: kube-node-service-lb
labels:
name: kube-node-service-lb
spec:
type: LoadBalancer
clusterIP: 10.99.201.198
ports:
- port: 80
targetPort: 8081
protocol: TCP
nodePort: 32145
selector:
app: web
status:
loadBalancer:
ingress:
- ip: 192.168.174.127 #这里是云服务商提供的负载匀衡器的IP地址
执行命令:
root@kube-master:/home/cong/Desktop/NodeDemo1# kubectl create -f service-lb.yaml
service/kube-node-service-lb created
root@kube-master:/home/cong/Desktop/NodeDemo1# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-node LoadBalancer 10.99.201.195 8081:31585/TCP 21m
kube-node-service NodePort 10.97.114.36 80:32143/TCP 1d
kube-node-service-lb LoadBalancer 10.99.201.198 80:32145/TCP 9s
kubernetes ClusterIP 10.96.0.1 443/TCP 8d
nginx NodePort 10.99.22.64 80:32322/TCP 2d
root@kube-master:/home/cong/Desktop/NodeDemo1# curl 10.99.201.195:8081
Hello World!
root@kube-slave-3:/home/cong# curl localhost:31585
Hello World!