๋กœ์ผ“๐Ÿพ
article thumbnail

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋Š” ๋‹ค๋ฅธ ํ”Œ๋žซํผ์ฒ˜๋Ÿผ ์ธ์ฆ(Authentication)/์ธ๊ฐ€(Athorization) ๋ฅผ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ธ์ฆ๋ฐ›์ง€ ๋ชปํ•œ ์‚ฌ์šฉ์ž๋ผ๋ฉด 401 (UnAuthorized) ๋ฅผ ์‘๋‹ต ๋ฐ›๊ณ , ์ธ์ฆ์€ ๋˜์—ˆ์ง€๋งŒ ๊ถŒํ•œ์ด ์—†๋‹ค๋ฉด 403(Forbidden) ์‘๋‹ต์„ ๋ฐ›๊ฒŒ ๋˜์ฃ .

์•„์ฃผ ํ‰๋ฒ”ํ•œ ์ธ์ฆ/์ธ๊ฐ€ ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ธ์ฆ/์ธ๊ฐ€๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋‹ค๊ณ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํ™˜๊ฒฝ์— ๋ฐ”๋กœ ์ ์šฉํ•  ์ˆœ ์žˆ๋Š” ๊ฑด ์•„๋‹™๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋‚ธ ์š”์ฒญ์„ ์ ์šฉํ•˜๊ธฐ ์ง์ „ ํ•œ ๊ตฐ๋ฐ๋ฅผ ๋” ๋“ค๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ๋ฐ”๋กœ Adimission Controller ์ž…๋‹ˆ๋‹ค.

 

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” Adimission Controller ์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๊ณ , Adimission Controller ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณผ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค. ๐Ÿ˜Ž

 

Admission Controller ๊ฐ€ ๋ญ์ฃ ?


๊ณต์‹ ๋ฌธ์„œ์— ์žˆ๋Š” Admission Controller ๊ด€๋ จ ๊ธ€์„ ๋ฒˆ์—ญํ•ด๋ณด์ž๋ฉด ์ด๋ ‡์Šต๋‹ˆ๋‹ค.

 

Admission Controller ๋Š” ํด๋Ÿฌ์Šคํ„ฐ์˜ ์‚ฌ์šฉ ๋ฐฉ์‹์„ ์ œ์–ดํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ž…๋‹ˆ๋‹ค. ์ธ์ฆ/์ธ๊ฐ€๋œ API ์š”์ฒญ์„ Admission Controller ์ด ๊ฐ€๋กœ์ฑ„์–ด ์š”์ฒญ ๊ฐœ์ฒด๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์š”์ฒญ์„ ๋ชจ๋‘ ๊ฑฐ๋ถ€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒŒ์ดํŠธํ‚คํผ๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

Admission Controller Phases

 

์ด ๊ทธ๋ฆผ์ด ๋ฐ”๋กœ Admission Controller ์˜ Phases ์ด์ฃ . ์ธ์ฆ(Authentication)/์ธ๊ฐ€(Athorization) ๋ฅผ ๊ฑฐ์นœ ํ›„ Mutating Admission ๊ณผ Validating Admission ์ด API Request ๋ฅผ ๊ฐ€๋กœ์ฑ„๊ฒŒ ๋˜๋Š”๋ฐ ์ด 2๊ฐœ๊ฐ€ Admission Controller ์˜ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.

 

๊ฐ€๋กœ์ฑˆ API Request ๋Š” WebHook ๋ฐฉ์‹์œผ๋กœ Admission Controller Server ๋กœ ๋ณด๋‚ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์—ฌ๊ธฐ์„œ ์š”์ฒญ์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ๊ฑฐ๋ถ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋˜์ฃ .

 

Mutating Admission ์€ ์ฃผ๋กœ API Request ์˜ ๊ฐœ์ฒด๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์šฉ๋„์ด๊ณ , Validating Admission ์€ ์ฃผ๋กœ API Request ๋ฅผ ๊ฑฐ๋ถ€ํ•  ์ง€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

 

๋…ผ๋ฆฌ์ ์œผ๋กœ๋Š” ์ด ๋‘˜์˜ ์—ญํ• ์ด ๊ฐ๊ฐ€ ๋‹ค๋ฅด์ง€๋งŒ Validating Admission ์—์„œ ๊ผญ ๊ฑฐ๋ถ€๋งŒ ํ•  ํ•„์š” ์—†์ด ๊ฐœ์ฒด๋ฅผ ๋ณ€๊ฒฝํ•ด๋„ ๋ฌด๋ฐฉํ•ฉ๋‹ˆ๋‹ค.

 

Admission Controller ์˜ ๋Œ€ํ‘œ์ ์ธ ์˜ˆ๋กœ๋Š” LimitRanger ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ Admission Controller ์€ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด๋ผ๊ณ  ๋ง์”€๋“œ๋ ธ์ฃ ? 30๊ฐœ ์ •๋„์˜ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•ด์ฃผ๋Š”๋ฐ LimitRanger ์€ ๊ทธ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

 

LimitRanger ์€ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์— ํŒŒ๋“œ๋ฅผ ๋ฐฐํฌํ•  ๋•Œ ๋งŒ์•ฝ resource ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด default resource ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ์ž๋™์œผ๋กœ ์„ค์ •ํ•ด๋†“์€ resource ๋ฅผ ๊ฐ–๊ฒŒ๋˜๊ฑฐ๋‚˜, resource ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ํŒŒ๋“œ๋Š” ๋ฐฐํฌ ์ œํ•œ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

 

์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์–ด๋ ต์ง€ ์•Š์Šต๋‹ˆ๋‹ค. kube-apiserver.yaml ์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์ถ”๊ฐ€๋งŒ ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 10.178.0.2:6443
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - --encryption-provider-config=/etc/kubernetes/etcd/ec.yaml
    - --anonymous-auth=true
    - --advertise-address=10.178.0.2
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=LimitRanger # ์ถ”๊ฐ€
     
    ...

 

LimitRanger ๋ง๊ณ  ๋ˆˆ์—ฌ๊ฒจ๋ณผ๋งŒํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ PodSecurityPolicy ๊ฐ€ ์žˆ๋Š”๋ฐ์š”. ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ Pod ์™€ ๊ด€๋ จ๋œ ๋ณด์•ˆ ์ •์ฑ…์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ž…๋‹ˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค๋ฉด SecurityContext ๋Š” 1000 ์ด ์•„๋‹Œ root ๋กœ ์ƒ์„ฑํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด ํŒŒ๋“œ ์ƒ์„ฑ์„ ๊ฑฐ๋ถ€ํ•  ์ˆ˜ ์žˆ๋Š” ์ •์ฑ…์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์ฃ .

 

ํ•˜์ง€๋งŒ PodSeuciryPolicy ๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค v1.21 ์—์„œ deprecated ๋˜์—ˆ๊ณ , v1.25 ์—์„  ์™„์ „ํžˆ ์‚ญ์ œ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•  ์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์ด๋Ÿฌํ•œ ์ •์ฑ…์€ ์–ด๋–ป๊ฒŒ ์ƒ์„ฑํ•ด์„œ ์ ์šฉํ•ด์•ผ ํ• ๊นŒ์š”?

 

๋‹ต์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋งŒ๋“ค๋ฉด ๋˜์ฃ  ๐ŸคŸ

 

๊ทธ๋Ÿผ ํ•œ๋ฒˆ ๊ฐ„๋‹จํ•˜๊ฒŒ Admission Controller ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ฃ !

 

Admission Controller ๋ฅผ ์ง์ ‘ ๋งŒ๋“ค์–ด๋„ ๋˜์ง€๋งŒ, ์ด๋ฏธ ์ž˜ ๋งŒ๋“ค์–ด์ง„ CNCF ํ”„๋กœ์ ํŠธ ์ผ๋ถ€์ธ OPA Gatekeeper ๋ผ๋Š” ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์—์„œ ๋งค์šฐ ๋ฐ€๊ณ  ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์ด๊ธฐ๋„ ํ•˜๊ณ , ๊ฐœ๋ฐœํ•ด์•ผํ•œ๋‹ค๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€ ๋•Œ๋ฌธ์— ์•„๋งˆ ๋งŽ์€ ๋ถ„๋“ค์ด OPA Gatekeeper ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„๊นŒ ๋ผ๋Š” ์ƒ๊ฐ์€ ๋“ญ๋‹ˆ๋‹ค.

๊ทธ๋ž˜๋„ ์›๋ฆฌ๋Š” ๋ฌด์—‡์ธ์ง€ ํŒŒ์•…ํ•˜๊ณ  ์‹ถ์œผ๋‹ˆ ๋งŒ๋“ค์–ด๋ณด์ฃ .

 

 

Admission Controller ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž!


๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“ค๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— Node.js ์˜ Express ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

Node ๋ฒ„์ „์€ 18.5 ์—์„œ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.

 

Express ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์ค๋‹ˆ๋‹ค. ์ดํ›„ package.json ์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

"scripts": {
    "start": "node ./bin/www",
    "dev": "nodemon app start",
    "prod": "pm2-runtime start app.js -i 1"
  }

 

 

ํ”„๋กœ์ ํŠธ ๊ด€๋ จ npm ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜๊ณ , ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

npm install -i nodemon pm2

npm run dev

 

Admission Controller Server ๋Š” ๋ฐ˜๋“œ์‹œ TLS ํ†ต์‹ ์„ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, http ํ†ต์‹ ์ด ์•„๋‹Œ https ๋กœ ํ†ต์‹ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

์ฝ”๋“œ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const bodyParser = require('body-parser');
const express = require('express');
const fs = require('fs');
const https = require('https');

const app = express();
app.use(bodyParser.json());

# ์„œ๋ฒ„ 8443 ๋ฆฌ์Šค๋‹
const port = 8443; 

# tls ํ†ต์‹ ์— ์‚ฌ์šฉํ•  ca.crt, server.crt, server.key ์ฝ๊ธฐ
const options = {
  ca: fs.readFileSync('ca.crt'),
  cert: fs.readFileSync('server.crt'),
  key: fs.readFileSync('server.key'),
};

# https ํ†ต์‹ 
const server = https.createServer(options, app);

# ์„œ๋ฒ„ ์‹คํ–‰
server.listen(port, () => {
  console.log(`Server running on port ${port}/`);
});

 

๊ทธ๋Ÿผ ์ด๋ฒˆ์—” ca.crt, server.crt, server.key ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์ฃ .

# CA Key ์™€ CA CRT ์ƒ์„ฑ
# X.509๋Š” PKI ๊ธฐ์ˆ  ์ค‘์—์„œ ๊ฐ€์žฅ ๋„๋ฆฌ ์•Œ๋ ค์ง„ ํ‘œ์ค€ ํฌ๋งท
openssl req -nodes -new -x509 -keyout ca.key -out ca.crt -subj "/CN=Admission Controller Webhook Demo CA" -sha256

# ์„œ๋ฒ„ Key ์ƒ์„ฑ
openssl genrsa -out server.key 2048

# server.conf ์ƒ์„ฑ
cat >server.conf <<EOF
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
prompt = no
[req_distinguished_name]
CN = admission-controller-server.default.svc
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = admission-controller-server.default.svc
EOF

# CSR ์ƒ์„ฑ
openssl req -new -key server.key -out server.csr -config server.conf

# Server CRT ์ƒ์„ฑ
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -extensions v3_req -extfile server.conf -sha256

 

์œ„ ๋ช…๋ น์–ด๋Œ€๋กœ ์ง„ํ–‰ํ•˜๋Š” ๊ฑธ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ์ด์ œ health check ์šฉ ์—”๋“œํฌ์ธํŠธ์™€ webhook ์šฉ ์—”๋“œํฌ์ธํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

app.get('/health', (req, res) => {
  res.send('ok');
});

app.post('/', (req, res) => {
  if (req.body.request === undefined) {
    res.status(400).send();
    return;
  }

  console.log(req.body); // DEBUGGING
  
	const { request: { uid } } = req.body;

  res.send({
    apiVersion: "admission.k8s.io/v1",
    kind: "AdmissionReview",
    response: {
      uid,
      allowed: validate(req)
    }
  })

});

// Create Pod ์— ๋Œ€ํ•œ ์ œํ•œ
function validate(req) {
  if (req.body['request']['object']['kind'] == 'Pod' && req.body['request']['operation'] == 'CREATE') {
    return false
  } else {
    return true
  }
}

 

GET /health ๋Š” health check ์šฉ ์—”๋“œํฌ์ธํŠธ์ด๊ณ , POST / ๋Š” webhook ์šฉ ์—”๋“œํฌ์ธํŠธ ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ฐ„๋‹จํ•˜๊ฒŒ Create Pod ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๋ฅผ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค.

 

์ฆ‰, Pod ์ƒ์„ฑ์€ ์ œํ•œ๋˜์ง€๋งŒ Pod ์™ธ์— Deploy ๋‚˜ Service ๋“ฑ์€ ์ƒ์„ฑ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

์ฐธ๊ณ ๋กœ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๊ฐ€ webhook ์œผ๋กœ ๋ณด๋‚ด๋Š” Request ๊ฐ์ฒด๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. 

์ž์„ธํ•œ ์ •๋ณด๋Š” ์—ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

{
    "kind": "AdmissionReview",
    "apiVersion": "admission.k8s.io/v1",
    "request": {
        "uid": "687a5fd9-0939-4d17-a398-d80582b199f8",
        "kind": {
            "group": "",
            "version": "v1",
            "kind": "Pod"
        },
        "resource": {
            "group": "",
            "version": "v1",
            "resource": "pods"
        },
        "requestKind": {
            "group": "",
            "version": "v1",
            "kind": "Pod"
        },
        "requestResource": {
            "group": "",
            "version": "v1",
            "resource": "pods"
        },
        "name": "hello-pod",
        "namespace": "default",
        "operation": "CREATE",
        "userInfo": {
            "username": "kubernetes-admin",
            "groups": []
        },
        "object": {
            "kind": "Pod",
            "apiVersion": "v1",
            "metadata": [],
            "spec": [],
            "status": []
        },
        "oldObject": null,
        "dryRun": "false",
        "options": {
            "kind": "CreateOptions",
            "apiVersion": "meta.k8s.io/v1",
            "fieldManager": "kubectl-client-side-apply",
            "fieldValidation": "Strict"
        },
        "apiVersion": "v1"
    }
}

 

๊ทธ๋Ÿผ ์ด์ œ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก Dockerfile ์„ ์ž‘์„ฑํ•˜์ฃ .

FROM node:12.18.2

RUN mkdir /var/node

COPY ./ /var/node

WORKDIR /var/node

RUN npm i

RUN npm i -g pm2

CMD [ "npm", "run", "prod" ]

 

๋ชจ๋“  ์ค€๋น„๊ฐ€ ๋๋‚ฌ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํ™˜๊ฒฝ์—์„œ ๋ฐฉ๊ธˆ ๋งŒ๋“  Adimission Controller Server ๋ฅผ ๋ฐฐํฌํ•ด๋ณด์ฃ  ๐Ÿ˜€

 

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์— ๋ฐฐํฌ


์ œ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ๋Š” kubeadm ์œผ๋กœ ๋งŒ๋“ค์—ˆ์œผ๋ฉฐ, v1.25 ์ž…๋‹ˆ๋‹ค.

 

admission-controller-server.yaml ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

apiVersion: v1
kind: Service
metadata:
  name: admission-controller-server
spec:
  ports:
  - port: 443
    protocol: TCP
    targetPort: 8443
  selector:
    run: admission-controller-server
---
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: admission-controller-server
  name: admission-controller-server
spec:
  containers:
  - image: kingbj0429/admission-controller-server
    name: admission-controller-server
    ports:
    - containerPort: 8443
    imagePullPolicy: Always
    livenessProbe:
      httpGet:
        port: 8443
        path: /health
        scheme: HTTPS
    readinessProbe:
      httpGet:
        port: 8443
        path: /health
        scheme: HTTPS

 

์—ฌ๊ธฐ์„œ ์ •๋ง์ •๋ง ์ค‘์š”ํ•œ๊ฒŒ ์žˆ๋Š”๋ฐ Service ์˜ .metadata.name ์€ ์œ„ server.crt ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ–ˆ๋˜ server.conf ์— ๋ช…์‹œํ•œ CN ๊ณผ ์ด๋ฆ„์ด ๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Service ์ด๋ฆ„์ด admission-controller-server ์ด๊ณ , Namespace ๊ฐ€ default ์ด๋‹ˆ admission-controller-server.default.svc ๊ฐ€ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด์ œ ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์ธ WebhookConfiguration ์„ ์ƒ์„ฑํ•ด์ฃผ์ฃ . mutate ์™€ valid 2 ์ข…๋ฅ˜๊ฐ€ ์žˆ๋Š”๋ฐ, ์—ฌ๊ธฐ์„  valid ๋กœ ์ƒ์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž์„ธํ•œ ์‚ฌํ•ญ์€ ์—ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: "pod-policy.example.com"
webhooks:
- name: "pod-policy.example.com"
  rules:
  - apiGroups:   ["*"]
    apiVersions: ["*"]
    operations:  ["CREATE"]
    resources:   ["*"]
    scope:       "Namespaced"
  clientConfig:
    service:
      namespace: "default"
      name: "admission-controller-server" # CN ๊ณผ ์ผ์น˜ํ•ด์•ผํ•จ
    caBundle: $(cat ca.crt | base64 | tr -d '\n')
  admissionReviewVersions: ["v1"]
  sideEffects: None
  timeoutSeconds: 5

 

๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜์ž๋ฉด CREATE ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ clientConfig ์— ๋“ฑ๋ก๋œ Service ๋„๋ฉ”์ธ(admission-controller-server)์œผ๋กœ webhook ์„ ๋ณด๋‚ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๋ชจ๋“  ์ค€๋น„๊ฐ€ ๋๋‚ฌ์œผ๋‹ˆ ์ œ๋Œ€๋กœ ๋˜์—ˆ๋Š” ์ง€ ํ™•์ธํ•ด๋ณด์ฃ .

 

Admission Controller Server ๊ฒ€์ฆ


์•„์ฃผ ์‹ฌํ”Œํ•œ Pod ๋ฅผ ์ƒ์„ฑํ•ด๋ณด์ฃ . ์ œ๋Œ€๋กœ ๋งŒ๋“ค์—ˆ๋‹ค๋ฉด ์ œํ•œ์ด ๋˜๊ฒ ์ฃ ?

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

 

Admission Webhook Denied ๊ฐ€ ๋‚œ ๊ฑธ ๋ณด๋‹ˆ ๋ฌธ์ œ๊ฐ€ ์—†์–ด ๋ณด์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค๋Š” ์–ด๋–จ๊นŒ์š”? 

Error from server: error when creating "nginx.yaml": admission webhook "pod-policy.example.com" denied the request without explanation

 

Deploy ๋กœ ํ…Œ์ŠคํŠธ ํ•ด๋ณด์ฃ .

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

 

์ƒ์„ฑ์ด ์•„์ฃผ ์ž˜๋ฉ๋‹ˆ๋‹ค.

deployment.apps/nginx-deployment created

 

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” Admission Controller ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ณ  ์ง์ ‘ Server ๋ฅผ ์ƒ์„ฑ๊นŒ์ง€ ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๊ธด ๊ธ€ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜Ž

 

์ฝ”๋“œ๋Š” ๊นƒํ—™์— ์žˆ์Šต๋‹ˆ๋‹ค 

profile on loading

Loading...