Kubernetes + private docker registry

kubernetes 설정이 완료 되었으면, 이제 실제로 kubernetes 를 사용하기 위한 docker registry 연동 설정을 해보겠습니다.

보통 회사에서 사용할 때는 자체 private docker registry 를 사용하고 있을 겁니다.

이 registry 를 kubectl 을 이용해서 연동해봅시다.

Set up Docker Registry

Pull an Image from a Private Registry – Kubernetes
위 글을 참고 하여 연동을 합니다.

등록

Usage:

kubectl create secret docker-registry NAME –docker-username=user –docker-password=password –docker-email=email [–docker-server=string] [–from-literal=key1=value1] [–dry-run] [options]

kubectl create secret docker-registry regcred --docker-server=https://example.com --docker-username=aws --docker-password="abcd1234" --docker-email="aws@example.com"

Docker-registry secret 이름을 여기서는 regcred로 생성해서 만들었습니다.

확인

kubectl get secret regcred --output=yaml

Output:

apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJodH3FovL2RyZWcuYcyI6eyJodH3FovMiLCJwYXNzd29yZCI6ImdyYWNlbm90ZTEyIUAiLC3D2KWFpbCI6ImF3c0BncmFjZW5vdGUuY29tIiwiYXV0aCI6IllYZHpPbWR5WVdObGJcyI6eyJodH3FovJ9fX0=
kind: Secret
metadata:
  creationTimestamp: 2018-07-11T06:15:56Z
  name: regcred
  namespace: default
  resourceVersion: "6036405"
  selfLink: /api/v1/namespaces/default/secrets/regcred
  uid: df5d178b-84d1-11e8-b74a-0e9d5423172c
type: kubernetes.io/dockerconfigjson

출력 결과에서 .dockerconfigjosn이라는 내용은 실제 docker registry 접속정보를 나타냅니다. 아래 명령을 통해 정상적으로 접속정보가 들어갔는지 확인 해 볼 수 있습니다.

kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 -d

맥북일 경우는 -d 옵션을 대문자  -D 로 변경합니다.  

kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 -D

Output:

{"auths":{"https://example.com":{"username":"aws","password":"abcd1234","email":"aws@example.com","auth":"YxDAOmdyKZNlbm30ZTEyIUA="}}}

TEST

이제 설정은 완료됐습니다.
실제 pod 를 배포해서 정상적으로 동작하는지 TEST 해 봅시다.

apiVersion: v1
kind: Pod
metadata:
  name: private-reg
spec:
  containers:
  - name: private-reg-container-nginx
    image: example.be/devops/nginx-custom:0.1.0
  imagePullSecrets:
  - name: regcred

위의 내용으로 my-private-reg-pod.yml 파일을 생성합니다.

kubectl create -f my-private-reg-pod.yml

위 명령 실행후 정상적으로 pod 생성이 되는지 확인합니다.

kubectl get po private-reg

Output:

 ✘ ktg@dev-vm-of00-016  ~/projects/k8s kubectl get po private-reg
NAME                            READY     STATUS    RESTARTS   AGE
private-reg                     1/1       Running   0          1m

STATUS 가 Running 이면 정상동작하는 것을 알수 있습니다.

curl로 nginx 작동 여부를 확인하고 싶다면,

kubectl exec -it private-reg (bash or sh)
curl localhost

위 명령을 실행 하면 됩니다.

golang migrate 사용시 에러

필요성

예전 golang 코드에 사용하고 있는 db migration 관리 라이브러리: migrate이 라이브러리는 기존 레포에서,
GitHub – mattes/migrate: Database migrations. CLI and Golang library. ->
아래 레포로 리포지토리가 변경되어 관리 중에 있었습니다.
GitHub – golang-migrate/migrate: Database migrations. CLI and Golang library.

기존 코드 수정이 필요해서 README 를 읽기 위해 들어왔다가 기존 코드가 예전과는 다르게 변경, 관리되는 것을 알게되어서 레포 변경을 하기로 마음을 먹었습니다.

문제

migrate up


변경 후 migrate up 실행시에 아래와 같은 문제가 발생했습니다.

error: pq: column “dirty” does not exist in line 0 · Issue #34 · golang-migrate/migrate · GitHub

아마 dirty 컬럼이 추가 된 듯 합니다.
dirty column 을 수동으로 추가해줍니다.

alter table schema_migrations add column dirty boolean not null default false;

다시 migrate 를 실행하면 정상동작합니다.

Postgres driver 를 사용할때 발생하는 문제


  • Postgres driver 를 사용할때 발생하는 문제
  • Migrate 라이브러리 import 후에 New, Up 코드 작성
  • Compile and Run
  • have panic….
panic: sql: Register called twice for driver postgres

goroutine 1 [running]:
database/sql.Register(0x1f34e5d, 0x8, 0x2794580, 0x281b590)
        /Users/ktg/.gvm/gos/go1.9/src/database/sql/sql.go:50 +0x1ad
github.com/golang-migrate/migrate/vendor/github.com/lib/pq.init.0()
        /Users/ktg/go/src/github.com/golang-migrate/migrate/vendor/github.com/lib/pq/conn.go:49 +0x5c
github.com/golang-migrate/migrate/vendor/github.com/lib/pq.init()
        <autogenerated>:1 +0x782
github.com/golang-migrate/migrate/database/postgres.init()
        <autogenerated>:1 +0x7d
devops-mocha3/cmd/mocha/setup.init()
        <autogenerated>:1 +0x5d
main.init()
        <autogenerated>:1 +0x78

처음엔 뭘 잘못 했나 싶어서 이것 저것 해봤는데, 동일 증상…

그러다 이런 글 발견
Driver is being registered twice · Issue #238 · lib/pq · GitHub

이번 문제는 vendor에 있는 파일(lib/pg)을 한번 호출 하고, 다시 GOPATH 에 있는 파일을 호출한 것.

수정을 위해 dep ensure 실행을 해줍니다.
그리고 다시 컴파일 후 실행하면 정상동작합니다.

Kong api gateway 설정 – 2

Kong api gateway 설정 – 2

여기서는 플러그인 활성화 하고 적용 및 테스트 하는 과정을 기록합니다.

첫번째 내용은 여기에..
Kong api gateway 설정 – 1 | 9to5의 개발하면서 겪은 경험

인증 auth


key auth

이제 인증 플러그인을 활성화 시켜보겠습니다.

Plugins – Key Authentication | Kong – Open-Source API Management and Microservice Management

Enable auth plugin on the service

curl -X POST http://localhost:8001/services/mocha/plugins \
  --data "name=key-auth"

Enable auth plugin on the routes

Routes ID 가 필요합니다.
ID 확인이 필요하면,

curl http://localhost:8001/routes

플러그인 활성화

curl -X POST http://localhost:8001/routes/cbaf40b1-196f-4e2b-9b47-b39d84c681a4/plugins \
    --data "name=key-auth" 

Create a Consumer

curl -X POST http://localhost:8001/consumers/ \
  --data "username=admin"

Create a Key

curl -X POST http://localhost:8001/consumers/admin/key-auth

Output:

{"id":"7026e178-9ab7-4bcc-a76a-2ab6b023b84d","created_at":1531989664000,"key":"fqS0sTQ9jM9qjlHNapnzFTJWfI5KGo8P","consumer_id":"69f5420a-6712-4ca2-8bc9-dcc964ebb4e4"}

이제 키 생성이 완료됐습니다.
위에서 등록한 api server 를 다시 호출 해봅시다.

curl -i -X GET \
  --url http://localhost:8000/ \
  --header 'Host: mocha1'

Output:

HTTP/1.1 401 Unauthorized
Date: Thu, 19 Jul 2018 08:43:33 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
WWW-Authenticate: Key realm="kong"
Server: kong/0.13.1

{"message":"No API key found in request"}

이제 plugin 이 enable 되어서 키 없이는 api 가 호출 되지 않습니다.

키를 넣고 다시 호출 합니다.

curl -i -X GET \
  --url http://localhost:8000/ \
  --header 'apikey: fqS0sTQ9jM9qjlHNapnzFTJWfI5KGo8P' \
  --header 'Host: mocha1'

Response code 200 확인 했습니다.

ldap

Plugins – LDAP Authentication | Kong – Open-Source API Management and Microservice Management

curl -X POST http://localhost:8001/routes/cbaf40b1-196f-4e2b-9b47-b39d84c681a4/plugins \
    --data "name=ldap-auth"  \
    --data "config.hide_credentials=true" \
    --data "config.ldap_host=ldap.example.com" \
    --data "config.ldap_port=389" \
    --data "config.start_tls=false" \
    --data "config.base_dn=dc=example,dc=com" \
    --data "config.verify_ldap_host=false" \
    --data "config.attribute=cn" \
    --data "config.cache_ttl=60" \
    --data "config.header_type=ldap

Allow multiple authentication methods per API and/or Consumer · Issue #590 · Kong/kong · GitHub

Kong의 ldap plugin 은 현재까지는 bind_dn을 입력할 수 가 없습니다.

아래 처럼 PR이 들어가 있는거 같긴 한데… 진행되고 있진 않는 듯합니다.
ldap_auth add bind+search feature by daurnimator · Pull Request #3093 · Kong/kong · GitHub

회사 ldap은 거의 bind_dn 을 사용할 것으로 보기 때문에 과감히 버려줍시다…

로그 logging

syslog 나 tcp-log 는 docker 상태에서는 동작하지 않는 것으로 보입니다.

해서, file-log plugin 을 enable해서 사용하는게 가장 간단한 것으로 보입니다.

file-log

file-log를 사용하기 위해서는 nginx 실행시 user 를 root 로 하는 것이 가장 간단 합니다. 아니면 아래의 에러를 보기 쉽상…..

[error] 76#0: [lua] handler.lua:56: [file-log] failed to open the file: Permission denied, context: ngx.timer, client: xxx.xxx.xxx.xxx, server: 0.0.0.0:8000

첫 번째 글에서 kong 을 docker 로 실행할 때 몇 개의 environment variables 이 추가 되어야합니다.

docker run -d --name kong \
    --link kong-database:kong-database \
    -e "KONG_DATABASE=postgres" \
    -e "KONG_PG_HOST=kong-database" \
    -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
    -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
    -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
    -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
    -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
    -e "KONG_ADMIN_LISTEN_SSL=0.0.0.0:8444" \
    -e "KONG_LOG_LEVEL=info" \
    -e "KONG_NGINX_USER=root" \
    -p 8000:8000 \
    -p 8443:8443 \
    -p 8001:8001 \
    -p 8444:8444 \
    kong:0.14.0-alpine

위 명령대로 다시 kong 을 실행하면 모든 로그가 docker logs 로 리다이렉트 되고, file-log를 활성화 시킬 수 있는 요건을 갖추게 됩니다.

plugin 활성화

  • services
curl -X POST http://localhost:8001/services/c5414169-73f8-4220-881a-0fb09a12973a/plugins \
    --data "name=file-log"  \
    --data "config.path=/dev/stdout"
  • plugins
curl -X POST http://localhost:8001/routes/a57bf14c-4c77-4990-8709-fb94ce006d2b/plugins \
    --data "name=file-log"  \
    --data "config.path=/dev/stdout"

로그 확인

docker logs -f --tail 100 kong

위 명령어로 도커 로그를 확인하면 이제 정상적으로 api 호출시에 로그가 찍히는 것을 확인 할 수 있습니다.

Kong api gateway 설정 – 1

Kong api gateway 설정 – 1


RESTful api 를 외부로 노출하지 않고 사용하기 위해(authentication, audit 기능 사용을 위한) Kong API 도입을 검토중입니다.

그러기 위해 직접 테스트 해보면서 내용을 여기에 정리하려 합니다.
관련된 모든 설치는 Docker 를 사용 하는 것으로 진행합니다.

Prerequisite

  • kong 0.13.1
  • dashboard v3.3.0
  • postgres 9.6

설치


kong 을 사용하기 위해 database 설정이 필요합니다.

CassandraPostgresql 중 선택 가능하지만 여기서는 postgresql 로 진행합니다.

postgresql

execute

sudo docker run -d --name kong-database \
              -p 5432:5432 \
              -e "POSTGRES_USER=kong" \
              -e "POSTGRES_DB=kong" \
              postgres:9.6-alpine

db migration

sudo docker run --rm \
    --link kong-database:kong-database \
    -e "KONG_DATABASE=postgres" \
    -e "KONG_PG_HOST=kong-database" \
    kong:latest kong migrations up

Kong

sudo docker run -d --name kong \
    --link kong-database:kong-database \
    -e "KONG_DATABASE=postgres" \
    -e "KONG_PG_HOST=kong-database" \
    -e "KONG_PROXY_ACCESS_LOG=/var/log/stdout" \
    -e "KONG_ADMIN_ACCESS_LOG=/var/log/stdout" \
    -e "KONG_PROXY_ERROR_LOG=/var/log/stderr" \
    -e "KONG_ADMIN_ERROR_LOG=/var/log/stderr" \
    -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
    -e "KONG_ADMIN_LISTEN_SSL=0.0.0.0:8444" \
    -p 8000:8000 \
    -p 8443:8443 \
    -p 8001:8001 \
    -p 8444:8444 \
    -v /root/log:/var/log \
    kong:0.13.1-alpine

Kong dashboard

Dashboard 는 사실 여기 글에서는 사용하지 않습니다.
Dashboard를 사용하기 위해서는 Dashboard 에 접속 후 UI 상에서 Creaate api를 해줘야합니다. (services 라는 메뉴가 없기 때문, apis 를 직접 등록하는 듯합니다.)
여기서는 따로 dashboard 관련 내용을 포스팅 하진 않겠습니다.

sudo docker run -d -p 8080:8080 \
  --link kong:kong \
  --name kong-dashboard \
  pgbi/kong-dashboard start \
  --kong-url http://kong:8001 \
  --basic-auth admin=admin

이제 설정을 완료했습니다.

실행

이제 실행을 위해 서비스를 등록 하겠습니다.

Configuring a Service – v0.13.x | Kong – Open-Source API Management and Microservice Management

이 링크를 참고했습니다.

  1. 서비스 생성

실제 접속해야할 endpoint (api server address)에 대한 url 을 입력해줍니다.

curl -i -X POST \
  --url http://localhost:8001/services/ \
  --data 'name=mocha' \
  --data 'url=http://10.110.10.124:8080' 
  1. 서비스의 호스트 생성

여기서는 hostname 을 지정해줍니다.
지정해준 이름을 사용해서, 실제. API 를 호출할 때 Host헤더를 이용해서 어느 서비스로 routing 할지를 판단합니다.

curl -i -X POST \
  --url "http://localhost:8001/services/mocha/routes/" \
  --data 'hosts[]=mocha1'
  1. 서비스 정상 작동 여부 확인

위에서 등록한 mocha1이라는 hostname 을 이용해서 실제 api server endpoint(여기서는 http://10.110.10.124:8080) 으로 routing 합니다.

curl -i -X GET \
  --url http://localhost:8000/ \
  --header 'Host: mocha1'

정상 작동 했다면 api server 의 response 를 받을 수 있습니다.

이제 설치는 완료했고, 다음은 인증을 위한 plugin 설치 입니다.