上篇文章,根据自己的理解,大致简述了k8s的定义和组件,这次来通过具体的案例,从创建pod,到配置ingress访问,了解k8s的一些常用命令,并通过实践来理解理论知识
本文的演示源于官网哦,官网的演示网站为https://kubernetes.io/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro/
搭建环境
本人在centos虚拟机安装 https://blog.youkuaiyun.com/kakaluoteyy/article/details/107821965,这个博客比较全面
出现的问题是:
1、提示swap等分区信息
解决方法是 vim /etc/fstab,注释掉最后一行
2、运行demo时,k8s官网的demo国内无法访问
解决方法如下:
vim pull-google.sh
保存内容如下
image=$1
echo $1
img=`echo $image | sed 's/k8s\.gcr\.io/anjia0532\/google-containers/g;s/gcr\.io/anjia0532/g;s/\//\./g;s/ /\n/g;s/_/-/g;s/anjia0532\./anjia0532\//g' | uniq | awk '{print ""$1""}'`
echo "docker pull $img"
docker pull $img
echo "docker tag $img $image"
docker tag $img $image
echo $1
img=`echo $image | sed 's/k8s\.gcr\.io/anjia0532\/google-containers/g;s/gcr\.io/anjia0532/g;s/\//\./g;s/ /\n/g;s/_/-/g;s/anjia0532\./anjia0532\//g' | uniq | awk '{print ""$1""}'`
echo "docker pull $img"
docker pull $img
echo "docker tag $img $image"
docker tag $img $image
然后赋予可执行权限 chmod u+x pull-google.sh
最后再用这个命令拉取的需要的镜像
./pull-google.sh gcr.io/google-samples/kubernetes-bootcamp:v1
输出如下:
gcr.io/google-samples/kubernetes-bootcamp:v1
docker pull anjia0532/google-samples.kubernetes-bootcamp:v1
v1: Pulling from anjia0532/google-samples.kubernetes-bootcamp
21ccaf2415f2: Pull complete
94055710d4b3: Pull complete
6eb5d001c9c0: Pull complete
ad83c3701fab: Pull complete
922fbba572e1: Pull complete
Digest: sha256:520432c28da38cd0d5c7d0a1da81bc69a99729738f4f696ad8ab65b9466d67b2
Status: Downloaded newer image for anjia0532/google-samples.kubernetes-bootcamp:v1
docker.io/anjia0532/google-samples.kubernetes-bootcamp:v1
docker tag anjia0532/google-samples.kubernetes-bootcamp:v1 gcr.io/google-samples/kubernetes-bootcamp:v1
docker pull anjia0532/google-samples.kubernetes-bootcamp:v1
v1: Pulling from anjia0532/google-samples.kubernetes-bootcamp
21ccaf2415f2: Pull complete
94055710d4b3: Pull complete
6eb5d001c9c0: Pull complete
ad83c3701fab: Pull complete
922fbba572e1: Pull complete
Digest: sha256:520432c28da38cd0d5c7d0a1da81bc69a99729738f4f696ad8ab65b9466d67b2
Status: Downloaded newer image for anjia0532/google-samples.kubernetes-bootcamp:v1
docker.io/anjia0532/google-samples.kubernetes-bootcamp:v1
docker tag anjia0532/google-samples.kubernetes-bootcamp:v1 gcr.io/google-samples/kubernetes-bootcamp:v1
上面执行完之后就可以正常执行k8s相关的命令创建pod了,然后拉取镜像时对应的就会做个映射
偶尔安装会出现swap等错误信息,即百度一下禁用swapp分区就行,在虚拟机会报内存不足,默认ram只有1g,关掉虚拟机设置为2gb即可
创建pod并进行访问操作
1、通过deployment创建pod和deployment
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
2、运行命令查看deployment运行情况,
kubectl get deployments
先是:
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 0/1 1 0 21s
kubernetes-bootcamp 0/1 1 0 21s
说明想创建一个deployment,而还没创建成功,所以avalable是0
过一会儿再看
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 1/1 1 1 7m1s
kubernetes-bootcamp 1/1 1 1 7m1s
说明成功了
3、查看po
kubectl get po
结果如下
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-57978f5f5d-jfgrm 1/1 Running 0 5m6s
pod启动成功
4再查看pod详细信息
Name: kubernetes-bootcamp-57978f5f5d-jfgrm
Namespace: default
Priority: 0
Node: docker-desktop/192.168.65.3
Start Time: Sun, 10 Jan 2021 20:01:50 +0800
Labels: app=kubernetes-bootcamp
pod-template-hash=57978f5f5d
Annotations: <none>
Status: Running
IP: 10.1.0.44
IPs:
IP: 10.1.0.44
Controlled By: ReplicaSet/kubernetes-bootcamp-57978f5f5d
Containers:
kubernetes-bootcamp:
Container ID: docker://2070dabc013be592aa41d14468183e0f601f094d7ef4f60eca0f2354c601c977
Image: gcr.io/google-samples/kubernetes-bootcamp:v1
Image ID: docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
Port: <none>
Host Port: <none>
State: Running
Started: Sun, 10 Jan 2021 20:01:51 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-l44lp (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-l44lp:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-l44lp
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 64s default-scheduler Successfully assigned default/kubernetes-bootcamp-57978f5f5d-jfgrm to docker-desktop
Normal Pulled 64s kubelet Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
Normal Created 64s kubelet Created container kubernetes-bootcamp
Normal Started 64s kubelet Started container kubernetes-bootcamp
通过这个命令,可以看到pod,的状态,所属的deployment,node节点信息可以看到是下载的docker desktop的ip信息,也就是类似于虚拟机的ip, 最后面还有events信息,通过master的scheduler进行指挥,然后交给具体的node节点的kubelete进行拉取进项,创建容器,启动容器
5、查看容器日志信息
kubectl logs kubernetes-bootcamp-57978f5f5d-jfgrm
日志内容如下:
Kubernetes Bootcamp App Started At: 2021-01-10T12:01:51.735Z | Running On: kubernetes-bootcamp-57978f5f5d-jfgrm
6、在容器执行命令
kubectl exec kubernetes-bootcamp-57978f5f5d-jfgrm env
返回内容为:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubernetes-bootcamp-57978f5f5d-jfgrm
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
NPM_CONFIG_LOGLEVEL=info
NODE_VERSION=6.3.1
HOME=/root
env命令是linux系统的命令
使用exec -it $podname bash进入容器命令,并使用linux命令进行操作,查看server.js文件发现是起了个8080端口的http服务,使用curl命令访问如下:
manzhang@SC02CM0FDMD6Q ~ % kubectl exec -it kubernetes-bootcamp-57978f5f5d-jfgrm bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@kubernetes-bootcamp-57978f5f5d-jfgrm:/# ls
bin boot core dev etc home lib lib64 media mnt opt proc root run sbin server.js srv sys tmp usr var
root@kubernetes-bootcamp-57978f5f5d-jfgrm:/# ls
bin boot core dev etc home lib lib64 media mnt opt proc root run sbin server.js srv sys tmp usr var
root@kubernetes-bootcamp-57978f5f5d-jfgrm:/# cat server.js
var http = require('http');
var requests=0;
var podname= process.env.HOSTNAME;
var startTime;
var host;
var handleRequest = function(request, response) {
response.setHeader('Content-Type', 'text/plain');
response.writeHead(200);
response.write("Hello Kubernetes bootcamp! | Running on: ");
response.write(host);
response.end(" | v=1\n");
console.log("Running On:" ,host, "| Total Requests:", ++requests,"| App Uptime:", (new Date() - startTime)/1000 , "seconds", "| Log Time:",new Date());
}
var www = http.createServer(handleRequest);
www.listen(8080,function () {
startTime = new Date();;
host = process.env.HOSTNAME;
console.log ("Kubernetes Bootcamp App Started At:",startTime, "| Running On: " ,host, "\n" );
});
root@kubernetes-bootcamp-57978f5f5d-jfgrm:/# curl 127.0.0.1:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-57978f5f5d-jfgrm | v=1
root@kubernetes-bootcamp-57978f5f5d-jfgrm:/#
deployment操作
上面创建pod是直接用create deployment命令来创建,比较简单,没有先写yml文件来配置
如果要用配置文件形式,可以用kubectl apply -f deployment.yaml --record 这种命令来进行,正常项目中肯定是通过yml等配置文件来启动的
https://blog.youkuaiyun.com/aizhaoa/article/details/107363539 这个博客上面有通过yaml文件配置来进行启动的,并且讲述了docker image的制作方法,有兴趣的可以看看
1、查看deployment配置
可以用以下命令来查看最终的配置
上面创建pod是直接用create deployment命令来创建,比较简单,没有先写yml文件来配置,其实通过命令来创建,可以用以下命令来查看最终的配置
kubectl edit deployment/kubernetes-bootcamp
会进入到类vim界面,可以编辑deployment信息
app: kubernetes-bootcamp
name: kubernetes-bootcamp
namespace: default
resourceVersion: "857512"
selfLink: /apis/apps/v1/namespaces/default/deployments/kubernetes-bootcamp
uid: dbd178b1-1842-4389-96c6-a9b0c9d1b01a
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: kubernetes-bootcamp
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: kubernetes-bootcamp
spec:
containers:
- image: gcr.io/google-samples/kubernetes-bootcamp:v1
imagePullPolicy: IfNotPresent
name: kubernetes-bootcamp
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 1
conditions:
- lastTransitionTime: "2021-01-10T12:01:52Z"
lastUpdateTime: "2021-01-10T12:01:52Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2021-01-10T12:01:50Z"
lastUpdateTime: "2021-01-10T12:01:52Z"
message: ReplicaSet "kubernetes-bootcamp-57978f5f5d" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 1
replicas: 1
updatedReplicas: 1
2、修改deployment
一把项目中,会修改deployment文件,然后通过jenkins来进行重启,不过可以动态修改deployment
在上文中,edit deployment之后,修改replicas 参数为2,也就是设置pod副本数为2,在get deployment如下;
get deployment kubernetes-bootcamp
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 2/2 2 2 31m
kubectl get po
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-57978f5f5d-4pprv 1/1 Running 0 3m3s
kubernetes-bootcamp-57978f5f5d-jfgrm 1/1 Running 0 33m
Service
之前讲过,service可以看做是对同一组pod的抽象,其相当大的作用就是对外expose
在master和node节点上可以访问pod,在项目中还可以本地通过ssh ip端口转发,将pod的ip端口映射到本地进行测试,但是在正式环境中肯定是没法访问的,况且pod ip也是会变化的,那就需要一个service
1、创建service
kubectl expose deployment kubernetes-bootcamp --type=LoadBalancer --port=8080
The type=LoadBalancer flag indicates that you want to expose your Service outside of the cluster
然后查看servie, 可以看到已经创建了pod,并且有cluster ip。(下面有一个serice是k8s自带的)
% kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 20d
kubernetes-bootcamp LoadBalancer 10.107.5.168 <pending> 8080:32272/TCP 15m
可以看到cluster IP和port信息,下文会再详细将port的几种区别
通过clusterIp对service进行访问,返回来的信息跟直接访问pod一样
curl 10.107.5.168:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-74b4587c5b-mhc9d | v=1
再通过node节点对service进行访问,由于本地虚拟机测试,直接用127.0.0.1进行访问:
可以看到8080:32272中8080是内部端口,而32272是外部访问的端口
# curl 127.0.0.1:32272
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-74b4587c5b-mhc9d | v=1
在跑到虚拟机所在的主机去访问虚拟机的ip+nodePort, 返回的信息一样,说明已经将service暴露到集群外面
% curl 172.16.237.132:32272
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-74b4587c5b-mhc9d | v=1
2、k8s的service信息
再详细查看一下service的信息
# kubectl get service kubernetes-bootcamp -oyaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2021-01-17T20:43:37Z"
labels:
app: kubernetes-bootcamp
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels:
.: {}
f:app: {}
f:spec:
f:externalTrafficPolicy: {}
f:ports:
.: {}
k:{"port":8080,"protocol":"TCP"}:
.: {}
f:port: {}
f:protocol: {}
f:targetPort: {}
f:selector:
.: {}
f:app: {}
f:sessionAffinity: {}
f:type: {}
manager: kubectl-expose
operation: Update
time: "2021-01-17T20:43:37Z"
name: kubernetes-bootcamp
namespace: default
resourceVersion: "14869"
uid: 62af9535-758c-4f17-99c0-e9ef1adb47a5
spec:
clusterIP: 10.107.5.168
clusterIPs:
- 10.107.5.168
externalTrafficPolicy: Cluster
ports:
- nodePort: 32272
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: kubernetes-bootcamp
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer: {}
<font color=red></font>
如图所示
可以看到有多种port: nodePort, port, targetPort
其中nodePort和port都是service的port,前者用来供集群外的服务调用,后者是集群内别的pod或者service调用
而targetPort是则是service接收外部的请求,转发到pod时的端口,最后到达pod容器的container Port上,更准确一/点的说法是,不管外部还是集群内部时,请求service会经过kube-proxy反向代理 -> pod target port -> container port
3、endpoints
使用下面命令,可以看到Endpoints字段,endpoints节点保存的就是service背后的pods信息,当pod被created或者die,那么endpoints就会相应地更新
# kubectl describe svc kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
Labels: app=kubernetes-bootcamp
Annotations: <none>
Selector: app=kubernetes-bootcamp
Type: LoadBalancer
IP Families: <none>
IP: 10.107.5.168
IPs: 10.107.5.168
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 32272/TCP
Endpoints: 10.244.0.23:8080,10.244.0.24:8080
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
Ingress
1、安装Ingress Contrller
首先需要部署Ingress Controoler
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
部署成功后,会生成pod
# kubectl get po -n ingress-nginx -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-6594ddb5dc-skbzc 1/1 Running 0 37m 10.1.0.8 docker-desktop <none> <none>
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-6594ddb5dc-skbzc 1/1 Running 0 37m 10.1.0.8 docker-desktop <none> <none>
进入pod去查看,会发现有一个nginx.conf
2、新建并且部署Ingress
新建文件example-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: hello.test.k8s.example.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubernetes-bootcamp
port:
number: 8080
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: hello.test.k8s.example.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubernetes-bootcamp
port:
number: 8080
部署
kubectl apply -f example-ingress.yaml
修改本地host,将域名映射到host
3、查看Ingress部署结果
Ingress部署成功后,会发现在ingress controller中nginx配置文件中自动更新了Ingress的信息
当通过域名访问时,先经过Ingress Controller的pod,找到Ingress,然后Ingress转发到本地服务中