Kubernetes——网络策略

网络策略(Network Policy)是用于控制分组的 Pod 资源彼此之间如何进行通信,以及分组的 Pod 资源如何与其他网络端点进行通信的规范。它用于为 Kubernetes 实现更为精细的流量控制,实现租户隔离机制。

  Kubernetes 使用标准的资源对象 "NetworkPolicy" 供管理员按需定义网络访问控制策略。

一、网络策略概述

  Kubernetes 的网络策略功能由其所使用的网络插件实现,因此,仅在使用那些支持网络策略功能的网络插件时才能够配置网络策略,如 Calico、Canal 及 kube-router 等。每种解决方案各有其特定的网络策略实现方式,它们的实现或依赖于节点自身的功能,或借助于 Hypervisor 的特性,也可能是网络自身的功能。Calico 的 calico/kube-controller 即为 Calico 项目中用于将用户定义的网络策略予以实现组件,它主要依赖于节点的 iptables 来实现访问控制功能。

  策略控制器用于监控创建 Pod 时所生成的新 API 端点,并按需为其附加网络策略。当发生需要配置策略的事件时,侦听器会监视到变化,控制器随即响应以进行接口配置和策略应用。

  Pod 的网络流量包含 "流入"(Ingress) 和 "流出"(Egress)两种方法,每种方向的控制策略则包含 "允许" 和 "禁止" 两种。

  默认情况下,Pod 处于非隔离状态,它们的流量可以自由来去。一旦有策略通过选择器规则则将策略应用于 Pod,那么所有未经明确允许的流量都将被网络策略拒绝,不过,其他未被选择器匹配的 Pod 不受影响。

二、部署 Canal 提供网络策略

  Canal 代表了针对云原生应用程序的最佳策略网络解决方案,旨在让用户轻松地将 Calico 和 flannel 网络部署在一起作为统一的网络解决方案,将 Calico 的网络策略执行与 Calico 和 flannel 叠加以及非叠加网络连接选项的丰富功能相组合。

  换句话说,Calico 项目既能够独立地为 Kubernetes 集群提供网络解决方案和网络策略,也能与 flannel 结合一起,由 flannel 提供网络解决方案,而 Calico 此时仅用于提供网络策略,这时我们也可以将 Calico 称为 Canal。Calico 将数据存储于 etcd 中,它支持选择使用专用的 etcd 存储,也能够以 Kubernetes API Server 作为后端存储,这里选择以第二种方式进行。

  结合 flannel 工作时,Calico 提供的默认配置清单中是以 flannel 默认使用的 10.244.0.0/16 作为 Pod 网络,因此,请确保 kube-controller-manager 程序在启动时通过 --cluster-cidr 选项设置使用了此网络地址,并且 --allocate-node-cidrs 的值应设置为 true。

1

2

--cluster-cidr=<your-pod-cidr>

--allocate-node-cidrs=true

  部署前,要在启用了 RBAC 的 Kubernetes 集群中设置必要的相关资源:

1

kubectl apply -f https://docs.projectcalico.org/v3.2/getting-started/kubernetes//installation/hosted/canal/rbac.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

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

# { {site.prodname}} Roles

# Reference { {site.url}}/{ {page.version}}/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml

kind: ClusterRole

apiVersion: rbac.authorization.k8s.io/v1beta1

metadata:

  name: calico

rules:

  - apiGroups: [""]

    resources:

      - namespaces

      - serviceaccounts

    verbs:

      - get

      - list

      watch

  - apiGroups: [""]

    resources:

      - pods/status

    verbs:

      - update

  - apiGroups: [""]

    resources:

      - pods

    verbs:

      - get

      - list

      watch

      - patch

  - apiGroups: [""]

    resources:

      - services

    verbs:

      - get

  - apiGroups: [""]

    resources:

      - endpoints

    verbs:

      - get

  - apiGroups: [""]

    resources:

      - nodes

    verbs:

      - get

      - list

      - update

      watch

  - apiGroups: ["networking.k8s.io"]

    resources:

      - networkpolicies

    verbs:

      - get

      - list

      watch

  - apiGroups: ["crd.projectcalico.org"]

    resources:

      - globalfelixconfigs

      - felixconfigurations

      - bgppeers

      - globalbgpconfigs

      - globalnetworksets

      - hostendpoints

      - bgpconfigurations

      - ippools

      - globalnetworkpolicies

      - networkpolicies

      - clusterinformations

    verbs:

      - create

      - get

      - list

      - update

      watch

---

# Flannel roles

# Pulled from https://github.com/coreos/flannel/blob/master/Documentation/kube-flannel-rbac.yml

kind: ClusterRole

apiVersion: rbac.authorization.k8s.io/v1beta1

metadata:

  name: flannel

rules:

  - apiGroups:

      ""

    resources:

      - pods

    verbs:

      - get

  - apiGroups:

      ""

    resources:

      - nodes

    verbs:

      - list

      watch

  - apiGroups:

      ""

    resources:

      - nodes/status

    verbs:

      - patch

---

# Bind the flannel ClusterRole to the canal ServiceAccount.

kind: ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1beta1

metadata:

  name: canal-flannel

roleRef:

  apiGroup: rbac.authorization.k8s.io

  kind: ClusterRole

  name: flannel

subjects:

- kind: ServiceAccount

  name: canal

  namespace: kube-system

---

# Bind the { {site.prodname}} ClusterRole to the canal ServiceAccount.

apiVersion: rbac.authorization.k8s.io/v1beta1

kind: ClusterRoleBinding

metadata:

  name: canal-calico

roleRef:

  apiGroup: rbac.authorization.k8s.io

  kind: ClusterRole

  name: calico

subjects:

- kind: ServiceAccount

  name: canal

  namespace: kube-system

  接下来即可部署 Canal 提供网络策略:

1

https://projectcalico.docs.tigera.io/v3.2/getting-started/kubernetes/installation/hosted/canal/canal.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

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

# Canal Version v3.2.8

# https://docs.projectcalico.org/v3.2/releases#v3.2.8

# This manifest includes the following component versions:

#   calico/node:v3.2.8

#   calico/cni:v3.2.8

#   coreos/flannel:v0.9.1

# This ConfigMap is used to configure a self-hosted Canal installation.

kind: ConfigMap

apiVersion: v1

metadata:

  name: canal-config

  namespace: kube-system

data:

  # The interface used by canal for host <-> host communication.

  # If left blank, then the interface is chosen using the node's

  # default route.

  canal_iface: ""

  # Whether or not to masquerade traffic to destinations not within

  # the pod network.

  masquerade: "true"

  # The CNI network configuration to install on each node.  The special

  # values in this config will be automatically populated.

  cni_network_config: |-

    {

      "name""k8s-pod-network",

      "cniVersion""0.3.0",

      "plugins": [

        {

          "type""calico",

          "log_level""info",

          "datastore_type""kubernetes",

          "nodename""__KUBERNETES_NODE_NAME__",

          "ipam": {

            "type""host-local",

            "subnet""usePodCidr"

          },

          "policy": {

              "type""k8s"

          },

          "kubernetes": {

              "kubeconfig""__KUBECONFIG_FILEPATH__"

          }

        },

        {

          "type""portmap",

          "snat"true,

          "capabilities": { "portMappings"true}

        }

      ]

    }

  # Flannel network configuration. Mounted into the flannel container.

  net-conf.json: |

    {

      "Network""10.244.0.0/16",

      "Backend": {

        "Type""vxlan"

      }

    }

---

# This manifest installs the calico/node container, as well

# as the Calico CNI plugins and network config on

# each master and worker node in a Kubernetes cluster.

kind: DaemonSet

apiVersion: extensions/v1beta1

metadata:

  name: canal

  namespace: kube-system

  labels:

    k8s-app: canal

spec:

  selector:

    matchLabels:

      k8s-app: canal

  updateStrategy:

    type: RollingUpdate

    rollingUpdate:

      maxUnavailable: 1

  template:

    metadata:

      labels:

        k8s-app: canal

      annotations:

        # This, along with the CriticalAddonsOnly toleration below,

        # marks the pod as a critical add-on, ensuring it gets

        # priority scheduling and that its resources are reserved

        # if it ever gets evicted.

        scheduler.alpha.kubernetes.io/critical-pod''

    spec:

      nodeSelector:

        beta.kubernetes.io/os: linux

      hostNetwork: true

      tolerations:

        # Make sure canal gets scheduled on all nodes.

        - effect: NoSchedule

          operator: Exists

        # Mark the pod as a critical add-on for rescheduling.

        - key: CriticalAddonsOnly

          operator: Exists

        - effect: NoExecute

          operator: Exists

      serviceAccountName: canal

      # Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force

      # deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods.

      terminationGracePeriodSeconds: 0

      containers:

        # Runs calico/node container on each Kubernetes node.  This

        # container programs network policy and routes on each

        # host.

        - name: calico-node

          image: quay.io/calico/node:v3.2.8

          env:

            # Use Kubernetes API as the backing datastore.

            - name: DATASTORE_TYPE

              value: "kubernetes"

            # Wait for the datastore.

            - name: WAIT_FOR_DATASTORE

              value: "true"

            # Set based on the k8s node name.

            - name: NODENAME

              valueFrom:

                fieldRef:

                  fieldPath: spec.nodeName

            # Don't enable BGP.

            - name: CALICO_NETWORKING_BACKEND

              value: "none"

            # Cluster type to identify the deployment type

            - name: CLUSTER_TYPE

              value: "k8s,canal"

            # Period, in seconds, at which felix re-applies all iptables state

            - name: FELIX_IPTABLESREFRESHINTERVAL

              value: "60"

            # No IP address needed.

            - name: IP

              value: ""

            # The default IPv4 pool to create on startup if none exists. Pod IPs will be

            # chosen from this range. Changing this value after installation will have

            # no effect. This should fall within `--cluster-cidr`.

            - name: CALICO_IPV4POOL_CIDR

              value: "192.168.0.0/16"

            # Disable file logging so `kubectl logs` works.

            - name: CALICO_DISABLE_FILE_LOGGING

              value: "true"

            # Set Felix endpoint to host default action to ACCEPT.

            - name: FELIX_DEFAULTENDPOINTTOHOSTACTION

              value: "ACCEPT"

            # Disable IPv6 on Kubernetes.

            - name: FELIX_IPV6SUPPORT

              value: "false"

            # Set Felix logging to "info"

            - name: FELIX_LOGSEVERITYSCREEN

              value: "info"

            - name: FELIX_HEALTHENABLED

              value: "true"

          securityContext:

            privileged: true

          resources:

            requests:

              cpu: 250m

          livenessProbe:

            httpGet:

              path: /liveness

              port: 9099

              host: localhost

            periodSeconds: 10

            initialDelaySeconds: 10

            failureThreshold: 6

          readinessProbe:

            httpGet:

              path: /readiness

              port: 9099

              host: localhost

            periodSeconds: 10

          volumeMounts:

            - mountPath: /lib/modules

              name: lib-modules

              readOnly: true

            - mountPath: /var/run/calico

              name: var-run-calico

              readOnly: false

            - mountPath: /var/lib/calico

              name: var-lib-calico

              readOnly: false

        # This container installs the Calico CNI binaries

        # and CNI network config file on each node.

        - name: install-cni

          image: quay.io/calico/cni:v3.2.8

          command: ["/install-cni.sh"]

          env:

            # Name of the CNI config file to create.

            - name: CNI_CONF_NAME

              value: "10-canal.conflist"

            # Set the hostname based on the k8s node name.

            - name: KUBERNETES_NODE_NAME

              valueFrom:

                fieldRef:

                  fieldPath: spec.nodeName

            # The CNI network config to install on each node.

            - name: CNI_NETWORK_CONFIG

              valueFrom:

                configMapKeyRef:

                  name: canal-config

                  key: cni_network_config

          volumeMounts:

            - mountPath: /host/opt/cni/bin

              name: cni-bin-dir

            - mountPath: /host/etc/cni/net.d

              name: cni-net-dir

        # This container runs flannel using the kube-subnet-mgr backend

        # for allocating subnets.

        - name: kube-flannel

          image: quay.io/coreos/flannel:v0.9.1

          command: [ "/opt/bin/flanneld""--ip-masq""--kube-subnet-mgr" ]

          securityContext:

            privileged: true

          env:

            - name: POD_NAME

              valueFrom:

                fieldRef:

                  fieldPath: metadata.name

            - name: POD_NAMESPACE

              valueFrom:

                fieldRef:

                  fieldPath: metadata.namespace

            - name: FLANNELD_IFACE

              valueFrom:

                configMapKeyRef:

                  name: canal-config

                  key: canal_iface

            - name: FLANNELD_IP_MASQ

              valueFrom:

                configMapKeyRef:

                  name: canal-config

                  key: masquerade

          volumeMounts:

          - name: run

            mountPath: /run

          - name: flannel-cfg

            mountPath: /etc/kube-flannel/

      volumes:

        # Used by calico/node.

        - name: lib-modules

          hostPath:

            path: /lib/modules

        - name: var-run-calico

          hostPath:

            path: /var/run/calico

        - name: var-lib-calico

          hostPath:

            path: /var/lib/calico

        # Used by flannel.

        - name: run

          hostPath:

            path: /run

        - name: flannel-cfg

          configMap:

            name: canal-config

        # Used to install CNI.

        - name: cni-bin-dir

          hostPath:

            path: /opt/cni/bin

        - name: cni-net-dir

          hostPath:

            path: /etc/cni/net.d

---

apiVersion: v1

kind: ServiceAccount

metadata:

  name: canal

  namespace: kube-system

---

# Create all the CustomResourceDefinitions needed for

# Calico policy and networking mode.

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

   name: felixconfigurations.crd.projectcalico.org

spec:

  scope: Cluster

  group: crd.projectcalico.org

  version: v1

  names:

    kind: FelixConfiguration

    plural: felixconfigurations

    singular: felixconfiguration

---

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  name: bgpconfigurations.crd.projectcalico.org

spec:

  scope: Cluster

  group: crd.projectcalico.org

  version: v1

  names:

    kind: BGPConfiguration

    plural: bgpconfigurations

    singular: bgpconfiguration

---

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  name: ippools.crd.projectcalico.org

spec:

  scope: Cluster

  group: crd.projectcalico.org

  version: v1

  names:

    kind: IPPool

    plural: ippools

    singular: ippool

---

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  name: hostendpoints.crd.projectcalico.org

spec:

  scope: Cluster

  group: crd.projectcalico.org

  version: v1

  names:

    kind: HostEndpoint

    plural: hostendpoints

    singular: hostendpoint

---

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  name: clusterinformations.crd.projectcalico.org

spec:

  scope: Cluster

  group: crd.projectcalico.org

  version: v1

  names:

    kind: ClusterInformation

    plural: clusterinformations

    singular: clusterinformation

---

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  name: globalnetworkpolicies.crd.projectcalico.org

spec:

  scope: Cluster

  group: crd.projectcalico.org

  version: v1

  names:

    kind: GlobalNetworkPolicy

    plural: globalnetworkpolicies

    singular: globalnetworkpolicy

---

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  name: globalnetworksets.crd.projectcalico.org

spec:

  scope: Cluster

  group: crd.projectcalico.org

  version: v1

  names:

    kind: GlobalNetworkSet

    plural: globalnetworksets

    singular: globalnetworkset

---

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  name: networkpolicies.crd.projectcalico.org

spec:

  scope: Namespaced

  group: crd.projectcalico.org

  version: v1

  names:

    kind: NetworkPolicy

    plural: networkpolicies

    singular: networkpolicy

三、配置网络策略

  Kubernetes 系统中,报文流入和流出的核心组件是 Pod 资源,因此它们也是网络策略功能生效的主要目标,因此,NetworkPolicy 对象也要使用标签选择器事先选择出一组 Pod 资源作为控制对象。

  一般来说,NetworkPolicy 是定义在一组 Pod 资源上的用于管控入栈流量的 "Ingress规则",或者说是管理出站流量的 "Egress规则",也可以是两者组合定义,而仅部分生效还是全部生效则需要由 spec.policyTypes 予以定义。

  默认情况下,Pod 对象既可以接受来自任何来源的流量,也能够向外部发出期望的的所有流量。而附加网络策略机制后,Pod 对象会因为 NetworkPolicy 对象的选定而被隔离。一旦名称空间中有任何 NetworkPolicy 对象匹配了某特定的 Pod 对象,则该 Pod 将拒绝 NetworkPolicy 所不允许的一切连接请求,而那些未被任何 NetworkPolicy 对象匹配到的其他 Pod 对象仍可接受所有流量。

  因此,就特定的 Pod 集合来说,入站 和 出站流量默认均处于放行状态,除非有规则能够明确匹配到它。一旦在 spec.policyTypes 中指定了生效的规则类型,却在 networkpolicy.spec 字段中嵌套定义了没有任何规则的 Ingress 或 Egress 字段时,则表示拒绝相关方向上的一切流量。

  定义网络策略时常用到的术语及说明具体如下:

    • Pod 组:由网络策略通过 Pod 选择器选定的一组 Pod 的集合,它们是规则生效的目标 Pod;可由 NetworkPolicy 对象通过 macthLabel 或 matchExpression 选定。
    • Ingress:入站流量,即由其他网络端点发往特定 Pod 组的流量,通常由流量发出的源站点(from)和流量的目标端口所定义。
    • Egress:出站流量,即由特定的 Pod 组发往其他网络端点的流量,通常由流量的目标网络端点(to)和端口(ports)来进行定义。
    • 端点(to,from):流量目标和流量源相关的组件,它可以是 CIDR 格式的IP地址块(ipBlock)、网络名称空间选择器(namespaceSelector)匹配的名称空间,或 Pod 选择器(podSelector)匹配的 Pod 组。
    • 端口(ports):TCP 或 UDP 的端口号。

  无论是 Ingress 还是 Egress 流量,与选定的某 Pod 组通信的另一方都可使用“网络端点”予以描述,它通常是某名称空间中的一个或一组 Pod 资源,由 namespaceSelector 选定名称空间后,经由 ipBlock 或 podSelector 进行指定。

  在 Ingress 规则中,网络端点也称为“源端点”,它们用 from 字段进行标识,而在 Egress 规则中,网络端点也称为“目标端点”,它们用 to 字段进行标识。不过,在未定义 Ingress 或 Egress 规则时,相关方向的流量均为“允许”,即默认为非隔离状态。而一旦在 networkpolicy.spec 中明确给出了 Ingress 或 Egress 字段,则它们的 from 或 to 字段的值就成了白名单列表,而空值意味着所有端点,即不限制访问。

四、管控入站流量

  以提供服务问主要目的的 Pod 对象通常是请求流量的目标对象,但它们的服务未必应该为所有网络端点所访问,这就有必要对它们的访问许可施加控制。

  networkpolicy.spec 中嵌套的 Ingress 字段用于定义入站流量规则,就特定的 Pod 集合来说,入站流量默认处于放行装填,除非在所有入站策略中,至少有一条规则能够明确匹配到它。Ingress 字段的值是一个对象列表,它主要由以下两个字段组成:

  • from<[]Object>:可访问当前策略匹配到的Pod对象的源地址对象列表,多个项目之间的逻辑关系为“逻辑或”的关系;若未设置此字段或其值为空,则匹配一切源地址(默认的访问策略为不限制);如果此字段至少有一个值,那么它将成为放行的源地址白名单,仅来源于此地址列表中的流量允许通过。
  • ports<[]Object>:当前策略匹配到的Pod集合的可被访问的端口对象列表,多个项目之间的逻辑关系为“逻辑或”的关系;若未设置此字段或其值为空,则匹配Pod集合上的所有端口(默认的访问策略为不限制);如果此字段至少有一个值,那么它将成为允许被访问的Pod端口白名单列表,仅入站流量的目标端口处于此列表中方才准许通过。

  需要注意的是,NetworkPolicy 资源属于名称空间级别,它的有效作用范围为其所属的名称空间。

1)设置默认的 Ingress 策略

  必要时,用户可以创建一个 NetworkPolicy 来为名称空间设置一个 "默认" 的隔离策略,该策略选择所有的 Pod 对象,而后允许或拒绝任何到达这些 Pod 的入站流量。

  例如下面的策略示例,其通过 policyTypes 字段指明要生效 Ingress 类型的规则,但未定义任何 Ingress 字段,因此不能匹配到任一源端点,从而拒绝所有入站流量:

1

2

3

4

5

6

7

8

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: deny-all-ingress # 没有设置命令空间则默认命令空间为default

spec:

  podSelector: {} # 空的 podSelector 表示选择命名空间下的所有pod

  policyTypes: ["Ingress"# 入口网络策略

 # 未设置进入条件,也就是不允许任何进入

  若要将默认策略设置为允许所有的入站流量,则只需要显式定义 Ingress 字段,并将其值设置为空以匹配所有源端点即可。如下面示例中的定义,没有为入站流量定义任何规则时,本身的默认规则即为允许访问,因此允许所有相关的入站流量时,本身无须定义默认规则,下面的示例只是为说明规则的定义格式:

1

2

3

4

5

6

7

8

9

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: allow-all-ingress

spec:

  podSelector: {}

  policyTypes: ["Ingress"]

  ingress:

  - {}

  实践中,通常将默认策略设置为拒绝所有的入站流量,而后显式放行允许的源端点的入站流量。

学习地址:Dpdk/网络协议栈/vpp/OvS/DDos/NFV/虚拟化/高性能专家(免费订阅,永久学习)

【文章福利】需要更多DPDK/SPDK学习资料加群793599096(资料包括C/C++,Linux,golang技术,内核,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,大厂面试题 等)可以自行添加学习交流群点击这里噢~

2)放行特定的入站流量

  在 Ingress 规则中嵌套 from 和 ports 字段即可匹配特定的入站流量,仅定义 from 字段时将隐含本地 Pod 资源组的所有端口,而仅定义 ports 字段时则表示隐含所有的源端点。from 和 ports 同时定义时表示隐含 "逻辑与" 关系,它将匹配到那些同时满足 from 和 ports 的定义的入站流量,即那些来自 from 指定的源端点,访问由当前 NetworkPolicy 的 podSelector 匹配的当前名称空间的 Pod 资源组上所指定的 ports 请求,如下图所示:

  from 字段的值是一个对象列表,它可嵌套使用 ipBlock、namespaceSelector 和 podSelector 字段来定义流量来源,此三个字段匹配 Pod 资源的方式各有不同,同时使用两个或以上的字段,彼此之间隐含 "逻辑或" 关系:

    • ipBlock <Object>: 根据 IP 地址或网络地址选择流量源端点。
    • namespaceSelector <Object>: 基于集群级别的标签挑选名称空间,它将匹配由此标签选择器选出的所有名称空间内的所有 Pod 对象;赋予字段以空值来表示挑选所有的名称空间,即源点为所有名称空间内的所有 Pod 对象。
    • podSelector <Object>: 于 NetworkPolicy 所在的当前名称空间内基于标签选择器挑选 Pod 资源,赋予字段以空值来表示挑选当前名称空间内的所有 Pod 对象。
    • ports: 字段的值也是一个对象列表,它嵌套 port 和 protocol 来定义流量的目标端口,即由 NetworkPolicy 匹配到的当前名称空间内的所有 Pod 资源上的端口。
    • port:端口号或在 Container 上定义的端口名称,未定义时匹配所有端口。
    • protocol: 传输层协议的名称,TCP 或 UDP,默认为 TCP。

  下面配置清单中的网络策略示例定义了如何开放 myapp pod 资源给相应的源站点访问:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: allow-myapp-ingress

  namespace: default

spec:

  podSelector:

    matchLabels:

      app: myapp

  policyTypes: ["Ingress"]

  ingress:

  - from:

    - ipBlock:

      cidr: 10.244.0.0/16

      except:

        - 10.244.3.0/24

    - podSelector:

      matchLabels:

        app: myapp

    ports:

    - protocol: TCP

      port: 80

  它将 default 名称空间拥有标签 "app=myapp" 的 Pod 资源的 80/TCP 端口开放给 10.244.0.0/16 网络内除 10.244.3.0/24 子网中的所有源端点,以及当前名称空间中拥有标签 "app=myapp" 的所有 Pod 资源访问,其他未匹配到的源端点的流量则取决于其他网络策略的定义,若没有任何匹配策略,则默认允许访问。

五、管控出站流量

  通常应该将出站流量的默认策略设置为准许通过。但如果有必要对其实施精细管理,仅放行那些有对外请求需要的 Pod 对象的出站流量,则也可先为名称空间设置“禁止所有”默认策略,而后定义明确的“准许”策略。

  networkpolicy.spec 中嵌套的 Egress 字段用于定义入站流量规则,就特定的 Pod 集合来说,出站流量一样默认处于放行状态,除非在所有入站策略中至少有一条规则能够明确匹配到它。
  Egress字段的值是一个字段列表,它主要由以下两个字段组成。

    • to<[]Object> :由当前策略匹配到的 Pod 资源发起的出站流量的目标地址列表,多个项目之间为“或”(OR)关系;若未定义或字段值为空则意味着应用于所有目标地址(默认为不限制);若明确给出了主机地址列表,则只有目标地址匹配列表中的主机地址的出站流量被放行。
    • ports<[]Object> :出站流量的目标端口列表,多个端口之间为“或”(OR)关系;若未定义或字段值为空则意味着应用于所有端口(默认为不限制);若明确给出了端口列表,则只有目标端口匹配列表中的端口的出站流量被放行。

 Egress规则中,to 和 ports 字段的值都是对象列表格式,它们可内嵌的字段分别与 Ingress 规则中的 from 和 ports 相同,区别仅是作用到的流量方向相反。

1)设置默认 Egress 策略

  通过创建一个 NetworkPolicy 对象来为名称空间设置一个默认的隔离策略,该策略选择所有的 Pod 对象,而后允许或拒绝由这些 Pod 发出的所有出站流量。

  通过 policyTypes 字段指明要生效 Egress 类型的规则,但未定义任何 Egress 字段,因此不能匹配到任何目标端点,从而拒绝所有的出站流量:

1

2

3

4

5

6

7

8

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: deny-all-egress

spec:

  podSelector: {} # 该命名空间下的所有pod

  policyTypes: ["Egress"# 出口网络策略

  # 未设置出口条件,也就是不允许任何出口流量

2.放行特定的出站流量

  示例中定义了一个Egress规则,它对来自拥有“app=tomcat”的Pod对象的,到达标签为“app=nginx”的Pod对象的80端口,以及到达标签为“app=mysql”的Pod对象的3306端口的流量给予放行:

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

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: allow-tomcat-egress

  namespace: default

spec:

  podSelector:

    matchLabels:

      app: tomcat

  policyTypes: ["Egress"]

  egress:

  - to:

    - podSelector:

      matchLabels:

        app: nginx

    ports:

    - protocol: TCP

      port: 80

  - to:

    - podSelector:

      matchLabels:

        app: mysql

    ports:

    - protocol: TCP

      port: 3306

  需要注意的,此配置清单中仅定义了出站规则,将入站流量的默认规则设置为拒绝所有时,还应该为具有标签 "app=tomcat" 的 Pod 对象放行入站流量。

六、隔离名称空间

  彼此隔离所有的名称空间,但应该允许它们都能够与 kube-system 名称空间中的 Pod 资源进行流量交换,以实现监控和名称解析等各种管理功能。

  下面示例为 default 名称空间定义了相关的规则,在出站和入站流量默认均为拒绝的情况下,它用于放行名称空间内部的各 Pod 对象之间的通信,以及与 kube-system 名称空间内各 Pod 间的通信:

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

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: namespace-deny-all

  namespace: default

spec:

  policyTypes: ["Ingress","Egress"]

  podSelector: {}

---

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: namespace-deny-all

  namespace: default

spec:

  policyTypes: ["Ingress","Egress"]

  podSelector: {}

  ingress:

  - from:

    - namespaceSelector:

        matchExpressions:

        - key: name

          operator: In

          values: ["default","kube-system"]

  egress:

  - to:

    - namespaceSelector:

        matchExpressions:

        - key: name

          operator: In

          values: ["default","kube-system"]

  需要注意的是,有些管理员可能会把一些系统附件部署到专有的名称空间中,例如把 Prometheus 监控系统部署到 prom 名称空间中等,所有这类的具有管理功能的附件所在的名称空间与每一个特定名称空间的出入流量都应该被放行。

七、网络策略应用案例

  假设有名为testing的名称空间内运行着一组nginx Pod和一组myapp Pod。要求实现如下目标。

1)myapp Pod仅允许来自nginx Pod的流量访问其80/TCP端口,但可以向nginx Pod的所有端口发出出站流量。
2)nginx Pod允许任何源端点对其80/TCP端口的访问,并能够向任意端点发出出站流量。
3)myapp Pod和nginx Pod都可与kube-system名称空间的任意Pod进行任何类型的通信,以便于可以使用由kube-dns提供的名称解析服务等

  如下图所示,出站和⼊站的默认策略是均为“禁⽌”。

  下面是测试实现步骤:

  第一步:

    1. 创建 testing 名称空间,并于其内基于 Deployment 控制器创建用于测试用的 nginx Pod 和 myapp Pod 各一个,创建相关Pod资源时顺便为其创建与 Deployment 控制器同名的 Service 资源:

      1

      2

      3

      kubectl create namespace testing

      kubectl run nginx --image=nginx:alpine --replicas=1 --namespace=testing --port 80 --expose --labels app=nginx

      kubectl run myapp --image=ikubernetes/myapp:v1 --replicas=1 --namespace=testing --port 80 --expose --labels app=myapp

    2. 为了便于在网络策略规则中引⽤ kube-system 名称空间,这⾥为其添加标签 “ns=kube-system”:

      1

      kubectl label namespace kube-system ns=kube-system

    3. 待相关资源创建完成后,即可通过与其相关的Service资源的名称访问相关的服务。例如,另外启动一个终端,使用 kubectl 命令在 default 名称空间中创建一个用于测试的临时交互式客户端:

      1

      kubectl run cirros-$RANDOM --namespace=default --rm -it --image=cirros --sh

    4. 而后基于此客户端分别测试访问 nginx 和 myapp 的服务,名称空间默认网络策略为准允许,接下来确认其访问请求可正常通过即可。

      1

      2

      3

      curl nginx.testing

      curl myapp.testing

  第二步:

    1. 定义网络策略清单文件(testing-netpol-denally.yaml),将testing名称空间的入站及出站的默认策略修改为拒绝访问,并再一次进行访问测试:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      apiVersion: networking.k8s.io/v1

      kind: NetworkPolicy

      metadata:

        name: deny-all-traffic

        namespace: testing

      spec:

        podSelector: {}

        policyTypes:

        - Ingress

        - Egress

    2. 接下来,将 testing-netpol-denyall.yaml 定义的默认策略 deny-all-traffic 予以应用,为 testing 名称空间设置默认的网络策略:

      1

      kubectl apply -f testing-netpol-denyall.yaml

    3. 回到第一步创建的交互式客户端,再次对 nginx 和 myapp 发起访问测试。为了避免长时间等待,这里为 curl 命令添加 --connect-timeout 选项为其定义连接超时时长。由下面的命令可知,此时无法再访问到 nginx 和 myapp 的相关服务:

      1

      2

      3

      curl --connect-timeout 2 nginx.testing

      curl --connect-timeout 2 myapp.testing

  第三步:

    1. 定义流量放行规则配置清单 nginx-allow-all.yaml,放行 nginx Pod 之上 80/TCP 端口的所有流量:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      apiVersion: networking.k8s.io/v1

      kind: NetworkPolicy

      metadata:

        name: nginx-allow-all

        namespace: testing

      spec:

        podSelector:

          matchLabels:

            app: nginx

        ingress:

        - ports:

          - port: 80

        - from:

          - namespaceSelector:

            matchLabels:

              ns: kube-system

        egress:

        - to:

        policyTypes:

        - Ingress

        - Egress

    2. 将上述清单文件中定义的网络策略应用至集群中以创建相应的网络策略:

      1

      kubectl apply -f nginx-allow-all.yaml

    3. 而后再次回到交互式测试客户端发起访问请求进行测试,由下面的命令结果可知,nginx 已经能够正常访问,这同时也意味着由 kube-system 名称空间中的 kube-dns 进行的名称解析服务也为可用状态:

      1

      2

      3

      4

      5

      curl --connect-timeout 2 nginx.testing

      ……

      <title> Welcome to nginx! <title>

      …… 

  第四步:

    1. 定义网络策略配置清单 myapp-allow.yaml,放行 testing 名称空间中来自 nginx Pod 的发往 myapp Pod 的 80/TCP 的访问流量,以及 myapp Pod 发往 nginx Pod 的所有流量。另外,允许 myapp Pod 与 kube-system 名称空间的任何Pod进行交互的所有流量:

      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

      apiVersion: networking.k8s.io/v1

      kind: NetworkPolicy

      metadata:

        name: myapp-allow

        namespace: testing

      spec:

        podSelector:

          matchLabels:

            app: myapp

        ingress:

        - from:

          - podSelector:

            matchLabels:

              app: nginx

          ports:

          - port: 80

        - from:

          - namespaceSelector:

            matchLabels:

              ns: kube-system

        egress:

        - to:

          - podSelector:

            matchLabels:

              app: nginx

          - to:

            - namespaceSelector:

              matchLabels:

                ns: kube-system

        policyTypes:

        - Ingress

        - Egress

    2. 接下来首先创建清单中定义的网络策略:

      1

      kubectl apply -f myapp-allow.yaml

    3. 然后切换至此前在专用终端中创建的临时使用的交互式 Pod,对 myapp Pod 发起访问请求。由下面的命令结果可知,其访问被拒绝:

      1

      curl --connect-timeout 2 http://myapp.testing

    4. myapp Pod 仅允许来自 nginx Pod 对其 80/TCP 端口的访问,于是,这里进入 testing 名称空间中的是 nginx Pod 的交互式接口,使用 wget 命令对 myapp Pod 发起访问请求:

      1

      2

      3

      4

      ~]$ kubectl exec -it nginx-b477df957-jb2nf -n testing -- /bin/sh

      # wget http://myapp.testing -O - -q

      Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

      #

转自:https://www.cnblogs.com/zuoyang/p/16444093.html

猜你喜欢

转载自blog.csdn.net/lingshengxiyou/article/details/129998725