ksaitoの日記

日々試したことの覚え書き

eksctlをコンパイルする

eksctlのソースをコンパイルしました。

golang 1.12以上の環境がなかったので、コンテナでやりました。

コンテナの準備

コンテナは、下記の通り準備しました。 golangのオフシャルコンテナには、makeやgitがインストールされているので、ほとんど手を加える必要はありませんでした。

$ cat Dockerfile 
FROM golang:1.12.6

RUN mkdir -p /root/.ssh \
 && chmod 700 /root/.ssh
RUN apt-get update && apt-get install -y \
    time \
 && apt-get -y autoremove && rm -rf /var/lib/apt/lists/*

WORKDIR /root
$ docker build -t golang-dev .

実行とビルド

ドキュメントに従って、実行します。

$ docker run -it --rm golang-dev bash
root@b97e7c15991d:~# cd src
root@b97e7c15991d:~/src# git clone https://github.com/weaveworks/eksctl.git
root@b97e7c15991d:~/src# cd eksctl/
root@b97e7c15991d:~/src/eksctl# make install-build-deps
...
root@b97e7c15991d:~/src/eksctl# make test
...
root@b97e7c15991d:~/src/eksctl# make eksctl
make: 'eksctl' is up to date.
root@b97e7c15991d:~/src/eksctl# ./eksctl version
[ℹ]  version.Info{BuiltAt:"1562335031", GitCommit:"0.1.34-294-g4041d65a", GitTag:""}
root@b97e7c15991d:~/src/eksctl#

コンパイルには、結構、時間がかかりました。

yamlの書き換え

設定ファイルの雛形がyamlで提供されることが多くなりました。

これまでは、提供される雛形の書き換えが必要な箇所をsedで書き換えていましたが、yqを使ったほうが良さそうです。

aws-auth-cm.yaml

AWS EKSのワーカーノードをAWSマネージメントコンソールでセットアップする手順では、aws-auth-cm.yamlをダウンロードしてdata.mapRolesrolearnにワーカーノードのインスタンスロールのARNを設定する必要があります。

下記のようにすることでAWSが提供するテンプレートから直接、必要な設定を作ることができます。

$ curl -s curl -o aws-auth-cm.yaml https://amazon-eks.s3-us-west-2.amazonaws.com/cloudformation/2019-02-11/aws-auth-cm.yaml | yq -r -c '.data.mapRoles' | yq -y '(.[] | .rolearn)="arn:aaa/bbb"' > mapRoles
$ cat mapRoles 
- rolearn: arn:aaa/bbb
  username: system:node:{{EC2PrivateDNSName}}
  groups:
  - system:bootstrappers
  - system:nodes

あとは、これをデプロイするだけです。

$ kubectl --namespace=kube-system create configmap aws-auth --from-file=mapRoles 
configmap/aws-auth created
$ kubectl --namespace=kube-system get configmaps aws-auth -o yaml
apiVersion: v1
data:
  mapRoles: |
    - rolearn: arn:aaa/bbb
      username: system:node:{{EC2PrivateDNSName}}
      groups:
      - system:bootstrappers
      - system:nodes
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system

jsonとyaml

jsonを使う機会が増えました。

jsonファイルから情報を取得するときに、jqコマンドが便利ですが、yamlのほうが見た目がわかりやすいのです。

jqコマンドと同じように操作できて、yamljsonに相互変換できるyqコマンドが便利です。

インストール

下記のコマンドでインストールすることができます。

pip install yq

jsonからyamlへの変換

オープンデータからjsonデータを取ってきます。

$ curl -s https://catalog.data.gov/harvest/object/345de16e-2fd5-4c52-9487-0467de11ad99 
{"accessLevel": "public", "bureauCode": ["005:12"], "contactPoint": {"@type": "vcard:Contact", "fn": "Brian Brotsos", "hasEmail": "mailto:brian.brotsos@usda.gov"}, "description": "USDA CIO Governance Board Membership List include all governance boards the CIO is a member of. Agencies shall keep this list up to date at least annually beginning in April 2016. This file is distributed for FITARA guidance https://management.cio.gov/ and more information on this format can be found at https://management.cio.gov/schema/", "distribution": [{"@type": "dcat:Distribution", "downloadURL": "http://www.usda.gov/digitalstrategy/governanceboards.json", "mediaType": "application/json", "title": "Governance Boards"}], "identifier": "usda-ocio-15-0008", "keyword": ["FITARA"], "landingPage": "http://www.usda.gov/wps/portal/usda/usdahome?navid=it-governance-boards", "license": "http://creativecommons.org/publicdomain/zero/1.0/", "modified": "2015-08-27", "programCode": ["005:059"], "publisher": {"@type": "org:Organization", "name": "Office of Chief Information Officer", "subOrganizationOf": {"@type": "org:Organization", "name": "Department of Agriculture"}}, "title": "USDA Governance Boards"}

これをyamlに整形します。

$ curl -s https://catalog.data.gov/harvest/object/345de16e-2fd5-4c52-9487-0467de11ad99 | yq -y '.'
accessLevel: public
bureauCode:
- 005:12
contactPoint:
  '@type': vcard:Contact
  fn: Brian Brotsos
  hasEmail: mailto:brian.brotsos@usda.gov
description: USDA CIO Governance Board Membership List include all governance boards
  the CIO is a member of. Agencies shall keep this list up to date at least annually
  beginning in April 2016. This file is distributed for FITARA guidance https://management.cio.gov/
  and more information on this format can be found at https://management.cio.gov/schema/
distribution:
- '@type': dcat:Distribution
  downloadURL: http://www.usda.gov/digitalstrategy/governanceboards.json
  mediaType: application/json
  title: Governance Boards
identifier: usda-ocio-15-0008
keyword:
- FITARA
landingPage: http://www.usda.gov/wps/portal/usda/usdahome?navid=it-governance-boards
license: http://creativecommons.org/publicdomain/zero/1.0/
modified: '2015-08-27'
programCode:
- 005:059
publisher:
  '@type': org:Organization
  name: Office of Chief Information Officer
  subOrganizationOf:
    '@type': org:Organization
    name: Department of Agriculture
title: USDA Governance Boards

yamlからjsonへの変換

yamlに変換したデータを再度、jsonに変換します。

jqコマンドのフィルタも、そのまま使えるのがいいですね。

$ curl -s https://catalog.data.gov/harvest/object/345de16e-2fd5-4c52-9487-0467de11ad99 | yq -y '.' | yq '.'
{
  "accessLevel": "public",
  "bureauCode": [
    "005:12"
  ],
  "contactPoint": {
    "@type": "vcard:Contact",
    "fn": "Brian Brotsos",
    "hasEmail": "mailto:brian.brotsos@usda.gov"
  },
  "description": "USDA CIO Governance Board Membership List include all governance boards the CIO is a member of. Agencies shall keep this list up to date at least annually beginning in April 2016. This file is distributed for FITARA guidance https://management.cio.gov/ and more information on this format can be found at https://management.cio.gov/schema/",
  "distribution": [
    {
      "@type": "dcat:Distribution",
      "downloadURL": "http://www.usda.gov/digitalstrategy/governanceboards.json",
      "mediaType": "application/json",
      "title": "Governance Boards"
    }
  ],
  "identifier": "usda-ocio-15-0008",
  "keyword": [
    "FITARA"
  ],
  "landingPage": "http://www.usda.gov/wps/portal/usda/usdahome?navid=it-governance-boards",
  "license": "http://creativecommons.org/publicdomain/zero/1.0/",
  "modified": "2015-08-27",
  "programCode": [
    "005:059"
  ],
  "publisher": {
    "@type": "org:Organization",
    "name": "Office of Chief Information Officer",
    "subOrganizationOf": {
      "@type": "org:Organization",
      "name": "Department of Agriculture"
    }
  },
  "title": "USDA Governance Boards"
}

CRDのコントローラ

githubで公開されているサンプルのコントローラを動かしてみます。

sample-controllerの手順通りです。

sample-controllerのコンパイルと実行

下記のように実行します。

実行するとapi-version(v1alpha1)が見つからないとエラーが出ますが、気にせず進みます。

$ export GOPATH=$(pwd)
$ go get k8s.io/sample-controller
$ cd $GOPATH/src/k8s.io/sample-controller
$ go build -o sample-controller .
$ ./sample-controller --kubeconfig=$KUBECONFIG
E0615 21:03:49.428247    8457 reflector.go:125] k8s.io/sample-controller/pkg/generated/informers/externalversions/factory.go:117: Failed to list *v1alpha1.Foo: the server could not find the requested resource (get foos.samplecontroller.k8s.io)
E0615 21:03:50.430718    8457 reflector.go:125] k8s.io/sample-controller/pkg/generated/informers/externalversions/factory.go:117: Failed to list *v1alpha1.Foo: the server could not find the requested resource (get foos.samplecontroller.k8s.io)
...

CRDをデプロイして、そのリソースを作成します。

$ kubectl apply -f artifacts/examples/crd.yaml 
customresourcedefinition.apiextensions.k8s.io/foos.samplecontroller.k8s.io created
$ kubectl apply -f artifacts/examples/example-foo.yaml 
foo.samplecontroller.k8s.io/example-foo created
$

先程のエラーメッセージは、でなくなります。

下記の通り、デプロイしたリソースからdeploymentが作られます。

$ kubectl get deployments
NAME          READY   UP-TO-DATE   AVAILABLE   AGE
example-foo   1/1     1            1           11s
$

sample-controllerは、どこで動かしたらいいのかな?

CustomResourceDefinitions

KubernetesのCustomResourceDefinitionsを調べました。

公式ドキュメントのCRDを、そのままデプロイしました。

$ cat resourcedefinition.yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  # name must match the spec fields below, and be in the form: <plural>.<group>
  name: crontabs.stable.example.com
spec:
  # group name to use for REST API: /apis/<group>/<version>
  group: stable.example.com
  # list of versions supported by this CustomResourceDefinition
  versions:
    - name: v1
      # Each version can be enabled/disabled by Served flag.
      served: true
      # One and only one version must be marked as the storage version.
      storage: true
  # either Namespaced or Cluster
  scope: Namespaced
  names:
    # plural name to be used in the URL: /apis/<group>/<version>/<plural>
    plural: crontabs
    # singular name to be used as an alias on the CLI and for display
    singular: crontab
    # kind is normally the CamelCased singular type. Your resource manifests use this.
    kind: CronTab
    # shortNames allow shorter string to match your resource on the CLI
    shortNames:
    - ct
$ kubectl apply -f resourcedefinition.yaml
customresourcedefinition.apiextensions.k8s.io/crontabs.stable.example.com created
$

kubectl proxyを起動します。

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

下記の通りAPIのエンドポイントが作成されていることがわかります。

$ curl http://localhost:8001/apis/stable.example.com/
{
  "kind": "APIGroup",
  "apiVersion": "v1",
  "name": "stable.example.com",
  "versions": [
    {
      "groupVersion": "stable.example.com/v1",
      "version": "v1"
    }
  ],
  "preferredVersion": {
    "groupVersion": "stable.example.com/v1",
    "version": "v1"
  }
$ 

作成したCRDのリソースを作ります。

$ cat my-crontab.yaml 
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-new-cron-object
spec:
  cronSpec: "* * * * */5"
  image: my-awesome-cron-image
$ kubectl apply -f my-crontab.yaml 
crontab.stable.example.com/my-new-cron-object created
$ kubectl get crontab
NAME                 AGE
my-new-cron-object   34s
$

CRDを削除すると、リソースも削除されます。

$ kubectl delete -f resourcedefinition.yaml 
customresourcedefinition.apiextensions.k8s.io "crontabs.stable.example.com" deleted
$ kubectl apply -f resourcedefinition.yaml 
customresourcedefinition.apiextensions.k8s.io/crontabs.stable.example.com created
$ kubectl get crontab
No resources found.
$

kanikoでコンテナをビルドする

kanokoを使ってコンテナをdocker hubにpushします。

kanikoは、kubernetes上で動かしている例が多いのですが、コンテナなのでローカルのdocker環境でお手軽に動くのでは、と思ったのですが、いろいろ落とし穴がありました。

dockerhubへの認証情報

docker loginすると$HOME/.docker/config.jsonに作成されるファイルを使います。

Mac環境だと、credSstoreにkeychainが指定されるため、そのまま使うことはできなかったので下記のようなファイルを準備しました。

****の部分は、echo <dockerhubユーザ>:<dockerhubパスワード> | base64の結果を入れます。

$ cat ~/.ssh/docker.json 
{
        "auths": {
                "https://index.docker.io/v1/": {
                        "auth": "****"
                }
        },
        "HttpHeaders": {
                "User-Agent": "Docker-Client/18.06.1-ce (linux)"
        }
}

Dockerfileの準備

下記のようなDockerfileを準備します。

$ cat Dockerfile
FROM nginx:1.13.12-alpine

COPY static /usr/share/nginx/html
$ cat static/index.html 
<!doctype html>
<meta charset=utf-8>
Hello, World!
$

Dockerhubにregistoryを準備

Dockerhubにログインして適当なregistoryを準備します。(例えば、ユーザ名/hello)

kanikoでビルド&push

$ docker run -v $PWD:/workspace  -v $HOME/.ssh/docker.json:/kaniko/config.json  --env DOCKER_CONFIG=/kaniko  gcr.io/kaniko-project/executor:latest  -d ユーザ名/hello:latest
INFO[0000] Downloading base image nginx:1.13.12-alpine  
INFO[0003] Executing 0 build triggers                   
INFO[0003] Taking snapshot of full filesystem...        
INFO[0003] Skipping paths under /kaniko, as it is a whitelisted directory 
INFO[0003] Skipping paths under /proc, as it is a whitelisted directory 
INFO[0003] Skipping paths under /sys, as it is a whitelisted directory 
INFO[0003] Skipping paths under /dev, as it is a whitelisted directory 
INFO[0003] Skipping paths under /workspace, as it is a whitelisted directory 
INFO[0003] Using files from context: [/workspace/static] 
INFO[0003] COPY static /usr/share/nginx/html            
INFO[0003] Taking snapshot of files...                  
2019/06/14 06:46:06 existing blob: sha256:b430473be128c1302a75e8381dfbaa45182fec81db4f75b749e4896d7816c2ea
2019/06/14 06:46:06 existing blob: sha256:ff3a5c916c92643ff77519ffa742d3ec61b7f591b6b7504599d95a4a41134e28
2019/06/14 06:46:06 existing blob: sha256:7d4e05a01906143afc15671a53151ea9755dac230db376a8b8364b21ca774dbc
2019/06/14 06:46:06 existing blob: sha256:8aeac9a3205fce5e21ab65ccce330fe389a9aaf47e4b682970b1772ae25a1d73
2019/06/14 06:46:07 pushed blob sha256:c05093cd454d3b9b777da1374a0c92a3c2dd2c43819b563299cb49025a943412
2019/06/14 06:46:07 pushed blob sha256:1be502b12f4e82cb3dcf3df03a45489c807b414ab5c0225cffb788ff8fbcdc92
2019/06/14 06:46:08 index.docker.io/ユーザ名/hello:latest: digest: sha256:a15f1ec662f02fc7efa2871a7c4e53fcce3e0da40975d2686ffb11ccc94d2ec6 size: 1072
$

aws cliのTips

VPC

取得するデータ コマンド
デフォルトVPCのVPCIDを取得 aws ec2 describe-vpcs --query 'Vpcs[?IsDefault==`true`].VpcId' --output text
デフォルトVPCのサブネットIDを取得 aws ec2 describe-subnets --query 'Subnets[?VpcId==`'$VPCID'`].SubnetId' --output text | tr "\t" ,