---
# System prepended metadata

title: 使用NCP Operator集成K8s
tags: [NCP]

---

# 使用NCP Operator集成K8s
###### tags: `NCP`
&emsp;&emsp;本文介绍一下使用NCP Operator集成K8s与NSX-T的方法和注意事项. 除Operator方法外原集成方式依然可用, 原方法文档可以参考张敏(Matt)制作的手册. 张敏的文档中阐述了集成的准备事项, 部分原理, 和详细步骤以及问题排查问题方法. 我无法写得比他更好了, 所以本文只做少许补充材料, 主要说明如果使用NCP Operator集成K8s的方法和优点.

&emsp;&emsp;Matt文档链接: [NSX-T-NCP-k8s-部署手册-v3.1.0](https://onevmw-my.sharepoint.com/:w:/g/personal/taoh_vmware_com/EfdanmNpuLdPqqj9Ai1LThsBZJjpLGhjXF0LaLWTWTNA4A?e=28bRx4)

## NCP集成结构
图一, 说明了NCP可以理解为一个NSX-T的K8s Operator, 并不负责具体的转发层面执行工作, 只是作为指令的转发和API的翻译工作.
![](https://i.imgur.com/5Hx8pMl.png)

<br>

图二, 步骤7, NSX CNI为容器提供端口配置, 因为NSX CNI是用Python2写的(在/opt/cni/bin下), 所以每个VM Node必须安装Python2, 否则启动Pod时会报错无法启动网络沙箱容器.
![](https://i.imgur.com/ubPzUws.png)

<br>

图三阐述了OVS, NSX Kube Proxy,的工作职责
![](https://i.imgur.com/DU62czA.png)

<br>

NSX CNI控制OVS为每个容器仓(Pod)打上本地VLAN标签, 到达NSX-T的Segment时, NSX-T通过Hyperbus上的节点标签知道的Pod网络的归属. 从而才能将Pod分配到正确的Segment, 和执行对Pod的分布式防火墙.
![](https://i.imgur.com/YbIkzNU.png)

## NCP Operator
Operator是NCP的Oprator,并没有实现NCP+NCP Operator一体化. 简而言之NCP Operator目的是为了简化安装和集成NSX-T与K8s. 提炼几点要点NCP Operator要点:
1. NCP Operator简化集成参数, 集中在一个Configmap中完成
2. 简化TLS Ingress和OVS Kernel module的安装
3. 批量为VM Node打上Hyperbus所需要的标签
4. 简化与Openshift的集成

个人觉得生产部署中第三点很重要, VM Node节点多的话, 能够批量自动打标签不但快, 最终要的是减少了犯错的概率. 如果使用原安装方式集成的话, 可以用我个人写的批量为VM Node打标签的脚本[Rock写的批量为VIF打标签的脚本](https://github.com/Rock981119/tagnsxnode_vifs)

![](https://i.imgur.com/5i4w2Tg.png)

## 配置
### 准备事项
1. 每个VM Node最少两张VIF, VIF1作为Kubelet和管理网卡, VIF2作为数据通讯网卡托管给OVS
2. VM Node的两张网卡最好在相同T1 Router下, 否则需要手工做No SNAT.
3. 解压NCP安装包, 上传NCP Operator镜像, 推荐使用私有镜像仓库.
4. 规划好你想要的拓扑, 可以参考张敏的文档
其余地址池如,Pod Subnet, LB VIP Pool, Egress NAT Pool等可以参考官方文档或张敏的文档.

### 演示环境


| Product | Version            |
| ------- | ------------------ |
| NCP     | 3.1.2              |
| NSX-T   | 3.1.0              |
| K8s     | v1.18.9            |
| OS      | Ubuntu 18.04.5 LTS |
| Kernel  | 4.15.0-112-generic |
| Runtime | docker://19.3.13   |

NCP压缩包解压后, 在operator文件夹下kubernetes内有安装所需的所有YAML
```
/operator/kubernetes
kubernetes ls
configmap.yaml                                operator.nsx.vmware.com_ncpinstalls_crd.yaml  role_binding.yaml
lb-secret.yaml                                operator.nsx.vmware.com_v1_ncpinstall_cr.yaml service_account.yaml
namespace.yaml                                operator.yaml
nsx-secret.yaml                               role.yaml
```

### 准备YAML

* 先编辑operator.yaml
Operator的自己的镜像在压缩包内, 上传至私有镜像库或直接上传到节点上.

该环境变量指定了待会部署NCP时从何处拉取镜像, 我填的是私有镜像库
- name: NCP_IMAGE
              value: "192.168.31.250:5000/nsx-ncp:3.1.2"

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nsx-ncp-operator
  namespace: nsx-system-operator
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nsx-ncp-operator
  template:
    metadata:
      labels:
        name: nsx-ncp-operator
    spec:
      hostNetwork: true
      serviceAccountName: nsx-ncp-operator
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
      - effect: NoSchedule
        key: node.kubernetes.io/not-ready
      - effect: NoSchedule
        key: node.kubernetes.io/network-unavailable
      volumes:
      - hostPath: {path: /etc/os-release}
        name: host-os-release
      containers:
        - name: nsx-ncp-operator
          image: vmware/nsx-container-plugin-operator
          command: ["/bin/bash", "-c", "nsx-ncp-operator --zap-time-encoding=iso8601"]
          volumeMounts:
          - {mountPath: /host/etc/os-release, name: host-os-release}
          imagePullPolicy: IfNotPresent
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: OPERATOR_NAME
              value: "nsx-ncp-operator"
            - name: NCP_IMAGE
              value: "192.168.31.250:5000/nsx-ncp:3.1.2"
            - name: WATCH_NAMESPACE
              value: "nsx-system-operator"

```

编辑configmap.yaml, 篇幅问题, 至粘贴跟测试环境相关的选项
```
[coe]
    adaptor = kubernetes
    cluster = k8s-03-cluster
    node_type = HOSTVM
    
[nsx_v3]
    policy_nsxapi = True
    nsx_api_managers = 192.168.31.245
    nsx_api_user = admin
    nsx_api_password = VMware1!VMware1!
    insecure = True
    use_native_loadbalancer = True
    default_ingress_class_nsx = True
    client_ssl_profile = k8s-lb-profile
    ## 可选项, 如果要开始NSX-T LB对TLS Ingress的支持. k8s-lb-profile是我自定义的, 系统内有内置的Profile可以选择
    lb_default_cert_path = /etc/nsx-ujo/lb-cert/tls.crt
    ## 可选项, 如果要开始NSX-T LB对TLS Ingress的支持. LB默认证书的挂载位置
    lb_priv_key_path = /etc/nsx-ujo/lb-cert/tls.key
    ## LB默认私钥的挂载位置
    service_size = SMALL
    no_snat_ip_blocks = K8SC3_Pod_NoNAT_IPB
    external_ip_pools = K8SC3_Egress_IPP
    container_ip_blocks = K8SC3_Pod_IPB
    top_tier_router = K8C3-T1
    ## 选择了T1作为SNAT执行点
    single_tier_topology = True
    ## 拓扑模型选择Per T1 Per Cluster 
    single_tier_sr_topology = False
    external_ip_pools_lb = K8SC3_Ingress_IPP
    overlay_tz = c86d3989-ae46-461d-a0f9-caa63c195515
    edge_cluster = ff8ba3ff-e48d-49b6-b8ff-d498149290ad
    ## TZ & edge_cluster必须填写UUID, 不能写名字
    x_forwarded_for = INSERT
    
 [k8s]
    apiserver_host_ip = 172.16.0.200
    apiserver_host_port = 6443
    enable_multus = True
[nsx_node_agent]
    ovs_bridge = br-int
    ovs_uplink_port = ens192
```

由于我需要开启NSX-T LB 对TLS Ingress的支持, 需要上传一张默认LB证书, 官方文档有提供自签名证书的脚本如下:
```
#!/bin/bash 
host="www.example.com" 
filename=server
openssl genrsa -out ca.key 4096 openssl req -key ca.key -new -x509 -days 365 -sha256 -extensions v3_ca -out ca.crt -subj "/C=US/ST=CA/L=Palo Alto/O=OS3/OU=Eng/CN=${host}"

openssl req -out ${filename}.csr -new -newkey rsa:2048 -nodes -keyout ${filename}.key -subj "/C=US/ST=CA/L=Palo Alto/O=OS3/OU=Eng/CN=${host}" openssl x509 -req -days 360 -in ${filename}.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out ${filename}.crt -sha256
```
**Tips**: NSX-T不可以使用根证书与私钥作为LB证书, 手工上传时就会报错. 必须采用跟为证书为CSR签发的证书, 如官方脚本的例子. 如果你使用自己制作的证书, 最后手工上传测试, 无报错再使用.

将证书文档输出为Base64格式后, 填入lb-secret.yaml
```
cat tls.crt |base64 -w0
cat tls.key |base64 -w0
```
lb-secret.yaml
```
apiVersion: v1
data: {tls.crt: "<cat tls.crt |base64 -w0>", tls.key: "<cat tls.key |base64 -w0>"}
kind: Secret
metadata: {name: lb-secret, namespace: nsx-system-operator}
type: kubernetes.io/tls

```

最后编辑operator.nsx.vmware.com_v1_ncpinstall_cr.yaml, 我将addNodeTag设为True, Oper将自动为每个VM Node的VIF打标签.
```
apiVersion: operator.nsx.vmware.com/v1
kind: NcpInstall
metadata:
  name: ncp-install
  namespace: nsx-system-operator
spec:
  ncpReplicas: 1
  addNodeTag: True
```

建议按顺序Apply YAMLs, 当然你整个文件夹一次性Apply也行.
namespace.yaml
role.yaml
role_binding.yaml
service_account.yaml
lb-secret.yaml
nsx-secret.yaml
configmap.yaml
operator.nsx.vmware.com_ncpinstalls_crd.yaml
operator.nsx.vmware.com_v1_ncpinstall_cr.yaml
operator.yaml

## 校验
正常部署后大概会是这样一番景象, NCP Pod与Node Agent正常工作, CoreDNS正常工作.
![](https://i.imgur.com/F75QgeS.png)

NSX-T的界面中出现了跟namespace相关的segment
![](https://i.imgur.com/wewoUr6.png)

在Transmit Segment上检查每个Node VIF是否已经打上了正确的标签. 如果没有, 确保operator.nsx.vmware.com_v1_ncpinstall_cr.yaml里的addNodeTag设为True, 重启Operator, 再回来检查.
![](https://i.imgur.com/JVicSHN.png)

最后检查默认LB证书是否上传成功
![](https://i.imgur.com/dT2xnfE.png)
![](https://i.imgur.com/LDoE9Tu.png)

如果都校验功过说明你已经集成成功了, 部署几个Pod, 尝试发布Tls Ingress试试吧.