# 常用命令汇总

这里整理一些在使用Kubernetes时常用的命令，方便查询。

{% hint style="info" %}
**小技巧：**&#x53EF;以在命令后跟`-h`或`--help`查看命令的参数及参数详解。
{% endhint %}

## 查看资源

查看资源可以使用`get`，可以加上`-o wide`标志显示更多的信息。例如，查看Pod资源：

```bash
kubectl get pods
kubectl get pods -o wide
```

使用`describe`可以展示某一个特定的资源对象的详细信息。例如，列出Pod资源对象kubia的详情：

```bash
kubectl describe pods kubia
```

使用`-o custom-columns`可以自定义要展示的列，以及`--sort-by`对资源列表进行排序：

```bash
$ kubectl get pods -o custom-columns=POD:metadata.name,NODE:spec.nodeName --sort-by=spec.nodeName
POD                    NODE
curl                   minikube
curl-with-ambassador   minikube
downward               minikube
```

## 创建资源

创建资源通常分为两步：

1. 编写资源的YAML/JSON配置文件；
2. 使用`kubectl apply`或`kubectl create`命令根据配置文件创建资源。例如，根据配置文件`kubia.yaml`创建资源：

   ```bash
    kubectl apply -f kubia.yaml
   ```

{% hint style="info" %}
**Tips:** 编写配置文件时，多使用`kubectl explain`来查看对应资源的配置项的定义及写法。例如，查看`Deployment`的规格中的配置项：

```bash
kubectl explain deployments.spec
```

有些资源存在多个版本，可以通过 `--api-version` 指定具体的版本。例如，查看 `autoscaling/v2beta1` 组的 `hpa` 的配置项：

```bash
kubectl explain hpa --api-version=autoscaling/v2beta1
```

{% endhint %}

### 命令创建Pod

可以通过`kubectl run`命令快速创建一个Pod，用于调试：

```bash
kubectl run -it srvlookup --image=tutum/dnsutils --rm --restart=Never --requests='cpu=800m,memory=20Mi' -- dig SRV kubia.default.svc.cluster.local
```

{% hint style="info" %}
**Tips:**&#x20;

1. `-it`是`--stdin`和`--tty`的简写，即开启一个新的终端并且使用输入；
2. `--iamge`：指定Pod中容器的镜像；
3. `--rm`：在终止后立即删除该Pod；
4. `--restart`：什么情况下重启，当使用`Never`则表示该Pod是一次性Pod，无需重启；
5. `--requests`：指定 Pod 中该容器的资源申请量
6. `--`：最后面的`--`表示kubectl命令项已结束，后面跟的是Pod中的容器需要执行的命令；
   {% endhint %}

#### 在运行的容器中执行命令

可以通过`kubectl exec`命令快速执行，用于调试：

```bash
kubectl exec -it kubia-7nog1 -- /bin/bash
```

{% hint style="info" %}
**Tips:**&#x20;

1. `-it`是`--stdin`和`--tty`的简写，即开启一个新的终端并且使用输入；
2. `--`：最后面的`--`表示kubectl命令项已结束，后面跟的是Pod中的容器需要执行的命令；
   {% endhint %}

### 命令创建Service

可以使用`kubectl expose`命令创建一个Service资源对象。基础命令方式为：

```bash
kubectl expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP|SCTP] [--target-port=number-or-name] [--name=name] [--external-ip=external-ip-of-service] [--type=type] [options]
```

举个例子：

```bash
# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.
kubectl expose rc nginx --port=80 --target-port=8000

# Create a service for a replication controller identified by type and name specified in "nginx-controller.yaml", which serves on port 80 and connects to the containers on port 8000.
kubectl expose -f nginx-controller.yaml --port=80 --target-port=8000

# Create a service for a pod valid-pod, which serves on port 444 with the name "frontend"
kubectl expose pod valid-pod --port=444 --name=frontend

# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name "nginx-https"
kubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https

# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.
kubectl expose rc streamer --port=4100 --protocol=UDP --name=video-stream

# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.
kubectl expose rs nginx --port=80 --target-port=8000

# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.
kubectl expose deployment nginx --port=80 --target-port=8000
```

### 命令创建 Deployment

使用 `kubectl create deployment {name} --image={image} [--dry-run] [options]` 来创建 Deployment 资源。如下在命名空间 `foo` 中创建一个名为 `test` 的 Deployment：

```bash
kubectl create deployment test --image=luksa/kubectl-proxy -n foo
```

### 创建 Role

使用 `kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run] [options]` 命令来创建 Role 资源。如下，在命名空间 `bar`中创建一个名为 `service-reader` 的 Role，该 Role 具备 `get` 和 `list` 所有 Services 资源的权限：

```bash
kubectl create role service-reader --verb=get --verb=list --resource=services -n bar
```

### 创建 RoleBinding

使用 `kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run] [options]` 命令来创建 RoleBinding 资源。如下，在命名空间 `foo` 中创建一个名为 `test` 的 RoleBinding，其将名为 `foo:default` 的 ServiceAccount 与名为 `service-reader` 的 Role 绑定起来：

```bash
kubectl create rolebinding test --role=service-reader --serviceaccount=foo:default -n foo
```

### 创建 ClusterRole

使用 `kubectl create clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run] [options]` 命令来创建 ClusterRole 资源。如下，创建一个名为 `pv-reader` 的 Role，该 Role 具备 `get` 和 `list` 所有 PV 资源的权限：

```bash
kubectl create clusterrole pv-reader --verb=get,list --resource=persistentvolumes
```

### 创建 ClusterRoleBinding

使用 `kubectl create clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run] [options]` 命令来创建 ClusterRoleBinding 资源。如下，创建一个名为 `pv-test` 的 ClusterRoleBinding，并将名为 `pv-reader` 的 ClusterRole 与命名空间 `foo` 中的 `default` ServiceAccount 进行绑定：

```bash
kubectl create clusterrolebinding pv-test --clusterrole=pv-reader --serviceaccount=foo:default
```

## 修改资源

在Kubernetes中经常会遇到需要修改资源的时候，其实无非都是修改资源规格定义，然后进行升级而已。

可以通过下面的常用命令进行修改。

| 方法                | 作用                                                                  | 例子                                                                                                                                                                 |
| ----------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| kubectl edit      | 该命令会使用默认编辑器打开目标资源对象的资源配置，修改后，保存即可。                                  | 修改Deployment资源对象kubia：`kubectl edit deployment kubia`                                                                                                              |
| kubectl patch     | 可针对资源对象的单个资源属性进行修改。                                                 | 修改Deployment资源对象kubia的容器规格：`kubectl patch deployment kubia -p '{"spec": {"template": {"spec": {"containers": [{"name": "nodejs", "image": "luksa/kubia:v2"}]}}}}'` |
| kubectl apply     | 通过一个完整的YAML/JSON文件，应用其中的新值来修改对象。                                    | 修改Deployment资源的配置文件后，重新apply该文件：`kubectl apply -f kubia-deployment-v2.yaml`                                                                                        |
| kubect replace    | 将原有对象替换为YAML/JSON文件中定义的新对象。要求之前的对象必须存在，否则会报错。                       | 修改Deployment资源的配置文件后，使用replace替换原对象：`kubectl replace -f kubia-deployment-v2.yaml`                                                                                  |
| kubectl set image | 修改Pod、ReplicationController、ReplicaSet、Deployment、DemonSet、Job内的镜像。 | 修改Deployment资源对象kubia中名为`nodejs`容器的镜像为`luksa/kubia:v2`：`kubectl set image deployment kubia nodejs=luksa/kubia:v2`                                                  |

### 使用scale缩放资源

我们可以使用`kubectl scale`来缩放**Deployment**、**ReplicaSet**、**ReplicationController**和**StatefulSet**四种类型的资源。下面举几个例子：

```bash
# 将名为`foo`的RS副本数改为3
kubectl scale --replicas=3 rs/foo

# 根据配置文件`foo.yaml`将定义的资源对象副本数改为3
kubectl scale --replicas=3 -f foo.yaml

# 如果Deployment资源对象`mysql`当前的副本数为2的话，将其修改为3，否则不变
kubectl scale --current-replicas=2 --replicas=3 deployment/mysql

# 同时将多个资源对象的副本数修改为3
kubectl scale --replicas=3 rc/foo rc/bar rc/baz

# 将StatefulSet资源对象`web`的副本数修改为3
kubectl scale --replicas=3 statefulset/web
```

## 删除资源

删除资源只需要通过`delete`即可。强制删除可以加上`--force`和`--grace-period 0`这两个标记。例如，删除Pod资源对象kubia：

```bash
kubectl delete pods kubia
# 强制删除
kubectl delete pods kubia --force --grace-period 0
```

{% hint style="info" %}
**Tips:**&#x20;

1. `all`表示所有资源：`kubectl delete all`表示删除所有资源对象（当前命名空间下）；
2. `--all`表示所有资源对象：`kubectl delete pods --all`表示删除所有Pods资源的对象（当前命名空间下）；
   {% endhint %}

## 与集群资源对象通信

这里说的集群资源，主要是指**Service**和**Pod**资源对象。

### 通过port-forward进程与Pod通信

`port-forward`是一个进程，可以将本地的端口与Kubernetes集群中的Pod的端口进行映射。其可以与Service对象后端的Pod、Deployment接管的Pod等的端口进行映射。

基本架构图如下：

![port-forward端口映射架构图](https://2906552408-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6Ub8CloS5kJszh6xSR%2Fsync%2F08ff5028695bd77e8fcd3cf55d801f328895efe9.png?generation=1588594609393158\&alt=media)

基本命令为：

```bash
kubectl port-forward TYPE/NAME [options] [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]
```

举几个例子：

```bash
# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod
kubectl port-forward pod/mypod 5000 6000

# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in a pod selected by the deployment
kubectl port-forward deployment/mydeployment 5000 6000

# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in a pod selected by the service
kubectl port-forward service/myservice 5000 6000

# Listen on port 8888 locally, forwarding to 5000 in the pod
kubectl port-forward pod/mypod 8888:5000

# Listen on port 8888 on all addresses, forwarding to 5000 in the pod
kubectl port-forward --address 0.0.0.0 pod/mypod 8888:5000

# Listen on port 8888 on localhost and selected IP, forwarding to 5000 in the pod
kubectl port-forward --address localhost,10.19.21.23 pod/mypod 8888:5000

# Listen on a random port locally, forwarding to 5000 in the pod
kubectl port-forward pod/mypod :5000
```

### 通过API服务器与资源对象通信

Kubernetes的API服务器的很有用的一个功能就是可以通过代理直接访问指定的资源，或获得指定的资源的详细信息。通常发起HTTP请求的URL都是`proxy/`：

```
<apiServerHost>:<port>/api/v1/namespaces/<namespaceName>/pods/<podName>/proxy/<path>
```

由于API服务器具有安全保障，因此直接访问需要在请求中添加授权令牌。但是可以使用**kubectl客户端**建立代理的方式来与API服务器通信。开启代理的命令如下：

```bash
kubectl proxy --port 8080
```

> 在本地的8080端口上开启kubectl proxy

例如，请求当前在`default`命名空间中，名为`kubia-0`的Pod时，可以通过下面的URL请求（Pod需有程序监听在80端口接收请求）：

```bash
curl localhost:8080/api/v1/namespaces/default/pods/kubia-0/proxy/
```

现在每个请求都会经过两层代理，如下图：

![使用kubectl proxy转发请求至Pod](https://2906552408-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6Ub8CloS5kJszh6xSR%2Fsync%2Fadf11815dab840ebe7124c59cfb6f26f62b1f20f.png?generation=1588594608956771\&alt=media)

{% hint style="info" %}
**Tips:**&#x20;

1. API服务器即`kube-apiserver`这个Pod，其内部容器使用的网络类型为`hostNetwork`，监听`8443`端口；
2. Kubernentes宿主机的`docker0`网卡地址为172.17.0.1/16，因此API服务器通过该网口与Pod交流；
   {% endhint %}

访问**Service资源对象**同样可以采用这种方式，该资源对象的URL为：

```
<apiServerHost>:<port>/api/v1/namespaces/<namespaceName>/services/<serviceName>/proxy/<path>
```
