docker for macでElasticsearchを実行するときはメモリ設定に注意

elasticsearch exited with code 137 でdockerコンテナが落ちるので調べていた。 デフォルトはいくつなんだろう? 私の場合2GBになっていたので、OOMで落ちていた。

ググったら下記にたどりついて、docker for mac自体のメモリLimitかと気づいた。 Container crashes with code 137 when given high load · Issue #22211 · moby/moby · GitHub

f:id:road288:20190320221221p:plain
docker for mac

AWS Certified Developer Associate受かった。次の目標

Amazon - Badge Verification - CertMetrics

f:id:road288:20190315211401p:plain

Solutions Architect Associateの次に受けたAWS Certified Developer Associateも取得した。

スコアは791/1000。合格ラインが720なので、それほど余裕はなかった。

f:id:road288:20190315213735p:plain

AWSを仕事でも使っているのと、特に勉強する時間が無いまま試験に臨んでしまった。Udemyで講座を買ったけど、結局ほとんど見ず。

AWSのサービスを一通り知識としては知っているが、実際に使ったことがないものも多いので、具体的なことについて問われると困ってしまった問題が多かった。

Kinesisとか、ElasticBeanstalkとか、Cognitoとか、実際触ってみないと。

次はProfessionalだけど、いきなり受けても受かる気がしないので、まずは模擬試験から。

試験に受かると特典として次の任意の試験料の50% Off になったり、模擬試験が無料になったりする。今回は模擬試験無料のコードを使った。

これからの一ヶ月で仕事DevOps分野をかなりやると思うので、AWS Certified DevOps Engineer - Professional Practice を受けてみる。 オンライン試験だから任意のタイミングでいつ受けてもいいのだが、4月18日に予定を入れた。日時を決めて取り組んで習慣化していきたい。

Amazon Linux2でyumでnginx入れようとしたらamazon-linux-extras使ってって出てきたが

ちょっとした雑事でEC2でnginx使おうと思って、Amazon Linux 2 を初めて使ってEC2インスタンスをたててみた。

これまでのAmazon Linuxだと普通にyumが使えたと思うのだけど、今回は違った

$ sudo yum install nginx
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
パッケージ nginx は利用できません。
エラー: 何もしません


nginx is available in Amazon Linux Extra topic "nginx1.12"

To use, run
# sudo amazon-linux-extras install nginx1.12

Learn more at
https://aws.amazon.com/amazon-linux-2/faqs/#Amazon_Linux_Extras


[ec2-user@ip-172-31-44-107 ~]$ sudo yum install nginx1.12
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
パッケージ nginx1.12 は利用できません。
エラー: 何もしません

下記でインストールできた。

$ sudo amazon-linux-extras install nginx1.12
Installing nginx

Amazon Linux Extrasって何

aws.amazon.com

$ amazon-linux-extras
  0  ansible2                 available    [ =2.4.2  =2.4.6 ]
  2  httpd_modules            available    [ =1.0 ]
  3  memcached1.5             available    [ =1.5.1 ]
  4  nginx1.12=latest         enabled      [ =1.12.2 ]
  5  postgresql9.6            available    [ =9.6.6  =9.6.8 ]
  6  postgresql10             available    [ =10 ]
  8  redis4.0                 available    [ =4.0.5  =4.0.10 ]
  9  R3.4                     available    [ =3.4.3 ]
 10  rust1                    available    \
        [ =1.22.1  =1.26.0  =1.26.1  =1.27.2  =1.31.0 ]
 11  vim                      available    [ =8.0 ]
 13  ruby2.4                  available    [ =2.4.2  =2.4.4 ]
 15  php7.2                   available    \
        [ =7.2.0  =7.2.4  =7.2.5  =7.2.8  =7.2.11  =7.2.13  =7.2.14 ]
 16  php7.1                   available    [ =7.1.22  =7.1.25 ]
 17  lamp-mariadb10.2-php7.2  available    \
        [ =10.2.10_7.2.0  =10.2.10_7.2.4  =10.2.10_7.2.5
          =10.2.10_7.2.8  =10.2.10_7.2.11  =10.2.10_7.2.13
          =10.2.10_7.2.14 ]
 18  libreoffice              available    [ =5.0.6.2_15  =5.3.6.1 ]
 19  gimp                     available    [ =2.8.22 ]
 20  docker=latest            enabled      \
        [ =17.12.1  =18.03.1  =18.06.1 ]
 21  mate-desktop1.x          available    [ =1.19.0  =1.20.0 ]
 22  GraphicsMagick1.3        available    [ =1.3.29 ]
 23  tomcat8.5                available    \
        [ =8.5.31  =8.5.32  =8.5.38 ]
 24  epel                     available    [ =7.11 ]
 25  testing                  available    [ =1.0 ]
 26  ecs                      available    [ =stable ]
 27  corretto8                available    [ =1.8.0_192  =1.8.0_202 ]
 28  firecracker              available    [ =0.11 ]
 29  golang1.11               available    [ =1.11.3 ]
 30  squid4                   available    [ =4 ]
 31  php7.3                   available    [ =7.3.2 ]
 32  lustre2.10               available    [ =2.10.5 ]

現時点で使えるパッケージのリスト。かなり最新版が使える。

FACTFULNESS(ファクトフルネス)

FACTFULNESS(ファクトフルネス) 10の思い込みを乗り越え、データを基に世界を正しく見る習慣

FACTFULNESS(ファクトフルネス) 10の思い込みを乗り越え、データを基に世界を正しく見る習慣

話題になっている本だが、読んでよかった。世界は少しずつであるが確実に良くなっており、前向きな気持ちになれる。ただし、やたらと明るいというよりは、静かに光を見いだせる感じだ。

私が学生の頃は、「先進国」「発展途上国」という2分法で国を分類して学んだ。そのような区分は現在ではあてはまらなくなっているが、以前の認識のまま、国に対するイメージをもってしまいがちだ。 むしろ国内の格差のほうが問題になってきていて、日本の富裕層と中国の富裕層は似通っていて暮らしぶりも近いが、日本国内の富裕層と貧困層ではかなりの暮らしの違いがある。文化も考え方も違う。

本書で紹介されているような10個の傾向は心の中に留めておきたい。 これは、項目によっては「世界」という切り口でなくても、ある種のグループについての言説においては当てはまるものがある。

  1. 分断本能「世界は分断されている」という思い込み
  2. ネガティブ本能「世界はどんどん悪くなっている」という思い込み
  3. 直線本能「世界の人口はひたすら増え続ける」という思い込み
  4. 恐怖本能 危険でないことを、恐ろしいと考えてしまう思い込み
  5. 過大視本能 「眼の前の数字がいちばん重要だ」という思い込み
  6. パターン化本能「ひとつの例がすべてに当てはまる」という思い込み
  7. 宿命本能「すべてはあらかじめ決まっている」という思い込み
  8. 純化本能「世界はひとつの切り口で理解できる」という思い込み
  9. 犯人探し本能「誰かを責めれば物事は解決する」という思い込み
  10. 焦り本能「いますぐ手を打たないと大変なことになる」という思い込み

AWS Certified Solutions Architect - Associate(再)取得した。次の目標

受かった。 スコアは849点(1000点満点)。「セキュアなアプリケーションおよびアーキテクチャを規定する」のセクションだけ「再学習を要する」となっていて、あとは「十分な知識を有する」に分類されていた。 S3とか通信の暗号化周りの理解が浅かった感じ。

下記のリンクはデジタルバッジ。

www.certmetrics.com

Solutions Architect Associateの資格は2013年くらいに一度取得していたがその後更新せずExpireしてしまっていた。AWSはそのときからすごく変化しているので取り直した。その頃には扱っていなかった機能も多く出題されていたと思う。

試験は渋谷のテストセンターで受けた。試験が終わった瞬間に結果が表示されるが、スコアとか認定証とかは数日後にメールでリンクが送られてくる。

テスト勉強は下記の書籍に2回くらい目を通しただけで、4時間くらいかけた。 普段仕事でAWSを使っていることもあり、既存の知識でほぼ回答できた。

徹底攻略 AWS認定 ソリューションアーキテクト ? アソシエイト教科書

徹底攻略 AWS認定 ソリューションアーキテクト ? アソシエイト教科書

2019年2月はちょうど試験内容が更改されたタイミングらしい。が、そこまで違う感じはしなかった。

次の目標

AWS Certified Developer - Associateを3月13日に設定。 Solutions Architect Professinalに行きたかったけど、サンプル問題をパット見た感じ1ヶ月で受かる感じがしなかったので、ハードル低くしてDeveloperパスに進んでみようと思う。

OSQueryでOSの情報がSQLでとれる

osquery.io

OSQuery知らなかった。Facebookは個人情報面ではEvilなところがあるけど、作るOSSは良いものがある。

macならbrewで入る。ただしboostやらいろいろな依存ライブラリを入れるので結構時間がかかる。

必要になったらもっと調べたいけどとりあえず

> osqueryi

インタラクティブシェルに入って

osquery> select * from os_version;
+----------+---------+-------+-------+-------+--------+----------+---------------+----------+
| name     | version | major | minor | patch | build  | platform | platform_like | codename |
+----------+---------+-------+-------+-------+--------+----------+---------------+----------+
| Mac OS X | 10.14.3 | 10    | 14    | 3     | 18D109 | darwin   | darwin        |          |
+----------+---------+-------+-------+-------+--------+----------+---------------+----------+
osquery> select percent_remaining from battery;
+-------------------+
| percent_remaining |
+-------------------+
| 100               |
+-------------------+

とか。

参考

Auditing containers with osquery – ITNEXT

Operatorを作ってみる - SDKをベースにGoでControllerを書く

前回の続きで、今度はOperator SDKを使ってGoでControllerを書くかたちでOperatorを作ってみる。

下記を参照しながら作っていくが、例ではMemcachedのDeployment(レプリカ数:3)となっているが、これをmackerel-agentのDaemonSetとして作ってみる。 operator-sdk/user-guide.md at master · operator-framework/operator-sdk · GitHub

SDKのインストールまでは済んでいるので、プロジェクトの雛形を生成する。

ᐅ operator-sdk new mackerel-operator
INFO[0000] Creating new Go operator 'mackerel-operator'.
INFO[0000] Created cmd/manager/main.go
INFO[0000] Created build/Dockerfile

(中略)

(68/70) Wrote k8s.io/apiextensions-apiserver@0fe22c71c47604641d9aa352c785b7912c200562
(69/70) Wrote github.com/coreos/prometheus-operator@v0.26.0
(70/70) Wrote sigs.k8s.io/controller-tools@v0.1.8
INFO[0095] Run dep ensure done
INFO[0095] Run git init ...
Initialized empty Git repository in /Users/yamadanaoyuki/go/src/github.com/mackerel-operator/.git/
Auto packing the repository in background for optimum performance.
See "git help gc" for manual housekeeping.
INFO[0103] Run git init done
INFO[0103] Project creation complete.

ある程度まで、コードが自動生成される。

APIを追加する

ᐅ operator-sdk add api --api-version=kirishikistudios.com/v1alpha1 --kind=Mackerel
INFO[0000] Generating api version kirishikistudios.com/v1alpha1 for kind Mackerel.
INFO[0000] Created pkg/apis/kirishikistudios/v1alpha1/mackerel_types.go
INFO[0000] Created pkg/apis/addtoscheme_kirishikistudios_v1alpha1.go
INFO[0000] Created pkg/apis/kirishikistudios/v1alpha1/register.go
INFO[0000] Created pkg/apis/kirishikistudios/v1alpha1/doc.go
INFO[0000] Created deploy/crds/kirishikistudios_v1alpha1_mackerel_cr.yaml
INFO[0001] Created deploy/crds/kirishikistudios_v1alpha1_mackerel_crd.yaml
INFO[0005] Running deepcopy code-generation for Custom Resource group versions: [kirishikistudios:[v1alpha1], ]
INFO[0007] Code-generation complete.
INFO[0008] Running OpenAPI code-generation for Custom Resource group versions: [kirishikistudios:[v1alpha1], ]
INFO[0009] Created deploy/crds/kirishikistudios_v1alpha1_mackerel_crd.yaml
INFO[0009] Code-generation complete.
INFO[0009] API generation complete.

Controllerを追加・編集する

ᐅ operator-sdk add controller --api-version=kirishikistudios.com/v1alpha1 --kind=Mackerel
INFO[0000] Generating controller version kirishikistudios.com/v1alpha1 for kind Mackerel.
INFO[0000] Created pkg/controller/mackerel/mackerel_controller.go
INFO[0000] Created pkg/controller/add_mackerel.go
INFO[0000] Controller generation complete.

メインロジックである pkg/controller/mackerel/mackerel_controller.go の中身を少しみてみると

(コードはこちら)

   found := &appsv1.DaemonSet{}
    err = r.client.Get(context.TODO(), types.NamespacedName{Name: Mackerel.Name, Namespace: Mackerel.Namespace}, found)
    if err != nil && errors.IsNotFound(err) {
        // Define a new Daemonset
        dep := r.daemonsetForMackerel(Mackerel)
        reqLogger.Info("Creating a new Daemonset", "Daemonset.Namespace", dep.Namespace, "Daemonset.Name", dep.Name)
        err = r.client.Create(context.TODO(), dep)
        if err != nil {
            reqLogger.Error(err, "Failed to create new Daemonset", "Daemonset.Namespace", dep.Namespace, "Daemonset.Name", dep.Name)
            return reconcile.Result{}, err
        }
        // Daemonset created successfully - return and requeue
        return reconcile.Result{Requeue: true}, nil
    }

r.clientというのはKubernetesCRUDをできるクライアントを内蔵していて、実際に必要なリソース(今回はMackerelというCR)があるかどうかチェックして無ければ作成する、ということをやっている。

DaemonSetのリソースは下記のようにGoの構造体として生成するのだが、慣れないとYamlを書いたほうが簡単に感じる。コード補完に頼りつつ、ドキュメントを見つつ書いた。

func (r *ReconcileMackerel) daemonsetForMackerel(m *apiv1alpha1.Mackerel) *appsv1.DaemonSet {
    ls := labelsForMackerel(m.Name)

    dep := &appsv1.DaemonSet{
        TypeMeta: metav1.TypeMeta{
            APIVersion: "extensions/v1beta1",
            Kind:       "DaemonSet",
        },
        ObjectMeta: metav1.ObjectMeta{
            Name:      m.Name,
            Namespace: m.Namespace,
        },
        Spec: appsv1.DaemonSetSpec{
            Selector: &metav1.LabelSelector{
                MatchLabels: ls,
            },
            Template: corev1.PodTemplateSpec{
                ObjectMeta: metav1.ObjectMeta{
                    Labels: ls,
                },
                Spec: corev1.PodSpec{
                    Containers: []corev1.Container{{
                        Image: "mackerel/mackerel-agent:latest",
                        Name:  "mackerel-agent",
                        Env: []corev1.EnvVar{
                            {
                                Name:  "apikey",
                                //TODO get from ConfigMap or Secret
                                Value: "xxxxxxxxxxxxxx",
                            },
                            {
                                //TODO get from ConfigMap or Secret
                                Name:  "opts",
                                Value: "-role=minikube:mbp13",
                            },
                            {
                                Name:  "enable_docker_plugin",
                                Value: "1",
                            },
                        },
                        VolumeMounts: []corev1.VolumeMount{
                            {
                                Name: "docker-sock",
                                MountPath: "/var/run/docker.sock",
                            },
                            {
                                Name: "mackerel-id",
                                MountPath: "/var/lib/mackerel-agent/",
                            },
                        },
                    }},
                    Volumes: []corev1.Volume{
                        {
                            Name: "docker-sock",
                            VolumeSource: corev1.VolumeSource{
                                HostPath: &corev1.HostPathVolumeSource{Path: "/var/run/docker.sock"},
                            },
                        },
                        {
                            Name: "mackerel-id",
                            VolumeSource: corev1.VolumeSource{
                                HostPath: &corev1.HostPathVolumeSource{Path: "/var/lib/mackerel-agent/"},
                            },
                        },
                    },
                },
            },
        },
    }
    // Set Mackerel instance as the owner and controller
    _ = controllerutil.SetControllerReference(m, dep, r.scheme)
    return dep
}

CRDをデプロイする

ᐅ kubectl create -f deploy/crds/kirishikistudios_v1alpha1_mackerel_crd.yaml
customresourcedefinition.apiextensions.k8s.io "mackerels.kirishikistudios.com" created

Operatorのイメージをビルド&DockerHubにPushする

ᐅ operator-sdk build chokkoy/mackerel-operator:v0.0.1
INFO[0004] Building Docker image chokkoy/mackerel-operator:v0.0.1
Sending build context to Docker daemon  197.9MB
Step 1/7 : FROM alpine:3.8
 ---> 491e0ff7a8d5
Step 2/7 : ENV OPERATOR=/usr/local/bin/mackerel-operator     USER_UID=1001     USER_NAME=mackerel-operator
 ---> Using cache
 ---> 23212d49d23b
Step 3/7 : COPY build/_output/bin/mackerel-operator ${OPERATOR}
 ---> 508598d68109
Step 4/7 : COPY build/bin /usr/local/bin
 ---> 82ea47e91962
Step 5/7 : RUN  /usr/local/bin/user_setup
 ---> Running in 20736001278d
+ mkdir -p /root
+ chown 1001:0 /root
+ chmod ug+rwx /root
+ chmod g+rw /etc/passwd
+ rm /usr/local/bin/user_setup
Removing intermediate container 20736001278d
 ---> 495bc12d5160
Step 6/7 : ENTRYPOINT ["/usr/local/bin/entrypoint"]
 ---> Running in b3dbe6930311
Removing intermediate container b3dbe6930311
 ---> d159180ac21f
Step 7/7 : USER ${USER_UID}
 ---> Running in 3cf2c8f425b3
Removing intermediate container 3cf2c8f425b3
 ---> 99d8a5dbf5f3
Successfully built 99d8a5dbf5f3
Successfully tagged chokkoy/mackerel-operator:v0.0.1
INFO[0012] Operator build complete.
ᐅ docker push chokkoy/mackerel-operator:v0.0.1

このイメージ名:タグで deploy/operator.yamlのIMAGEを置き換えて、デプロイ

ᐅ kubectl create -f deploy/service_account.yaml
serviceaccount "mackerel-operator" created

ᐅ kubectl create -f deploy/role.yaml
role.rbac.authorization.k8s.io "mackerel-operator" created

ᐅ kubectl create -f deploy/role_binding.yaml
rolebinding.rbac.authorization.k8s.io "mackerel-operator" created

ᐅ kubectl create -f deploy/operator.yaml
deployment.apps "mackerel-operator" created

この状態で、OperatorのDeployment(Pod)が一台起動している

ᐅ kubectl get deployment
NAME                DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
mackerel-operator   1         1         1            1           6s
ᐅ kubectl get pods
NAME                                 READY     STATUS    RESTARTS   AGE
mackerel-operator-557ff88b57-gjh9w   1/1       Running   0          9s

CR(カスタムリソース)をデプロイする

ᐅ kubectl apply -f deploy/crds/kirishikistudios_v1alpha1_mackerel_cr.yaml
mackerel.kirishikistudios.com "example-mackerel" created

すると、mackerel-agentのDaemonSetが起動する。

ᐅ kubectl get pods
NAME                                 READY     STATUS    RESTARTS   AGE
example-mackerel-4m7d7               1/1       Running   0          7s
mackerel-operator-557ff88b57-gjh9w   1/1       Running   0          30s
ᐅ kubectl get ds
NAME               DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
example-mackerel   1         1         1         1            1           <none>          10s

Mackerel上で監視できている

f:id:road288:20190216114230p:plain

SDKを使ってOperatorを作る流れがなんとなくわかった。GoでKubernetesのリソースを制御できるのは面白い!

ソースコードはこちら

https://github.com/chokkoyamada/mackerel-operator-go