DNSについて

DNS for Services and Podsに説明が書いてあるけど、試してみないと今一つわからなかったのでメモを残しておく。

Pod + Service

まずは、普通にendpointとなるPod2つと普通のサービスの構成で色々試してみる。環境はminikube。 マニフェストファイルは下記。

$ cat pod-srv.yaml
apiVersion: v1                                                                  
kind: Service                                                                   
metadata:                                                                       
  name: my-service                                                              
spec:                                                                           
  selector:                                                                     
    name: busybox                                                               
  ports:                                                                        
  - name: foo                                                                   
    port: 1234                                                                  
    targetPort: 5678                                                            
---                                                                             
apiVersion: v1                                                                  
kind: Pod                                                                       
metadata:                                                                       
  name: busybox1                                                                
  labels:                                                                       
    name: busybox                                                               
spec:                                                                                                                           
  containers:                                                                   
  - name: busybox                                                               
    image: busybox                                                              
    command:                                                                    
    - sleep                                                                     
    - "3600"                                                                    
---                                                                             
apiVersion: v1                                                                  
kind: Pod                                                                       
metadata:                                                                       
  name: busybox2                                                                
  labels:                                                                       
    name: busybox                                                               
spec:                                                                                                                                
  containers:                                                                   
  - name: busybox                                                               
    image: busybox                                                              
    command:                                                                    
    - sleep                                                                     
    - "3600"        

このマニフェストでデプロイ。

$ kubectl apply -f stateless-normal-srv.yaml
service "my-service" created
pod "busybox1" created
pod "busybox2" created

名前解決してみるために、適当なPodを作る。

$ kubectl run -it --rm --restart=NEVER --image=centos dns-test -- /bin/sh
If you don't see a command prompt, try pressing enter.
# yum install -y bind-utils

まずはサービス名を名前解決。

# nslookup my-service
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      my-service
Address 1: 10.111.178.2 my-service.default.svc.cluster.local

Aレコードは10.111.178.2 my-service.default.svc.cluster.localでしょう。

次にSRVを確認してみる。 ドキュメントによると、SRVレコードは_<named-port._<protocol>.my-serviceなので、次のコマンドを実行。

# nslookup -q=SRV _foo._tcp.my-service
Server:     10.96.0.10
Address:    10.96.0.10#53

_foo._tcp.my-service.default.svc.cluster.local  service = 10 100 1234 my-service.default.svc.cluster.local.

service = <Priority> <Weight> <Port> <Target>のはずなので、Portが1234でマニフェスト通りとなってることが確認出来る。

Pod + Headless Service

次はHeadless Serviceにして同じことを確認してみる。マニフェストは下記。

$ cat pod-headless-srv.yaml
apiVersion: v1                                                                  
kind: Service                                                                   
metadata:                                                                       
  name: my-service                                                              
spec:                                                                           
  selector:                                                                     
    name: busybox                                                               
  clusterIP: None                                                               
  ports:                                                                        
  - name: foo                                                                   
    port: 1234                                                                  
    targetPort: 5678                                                            
---                                                                             
apiVersion: v1                                                                  
kind: Pod                                                                       
metadata:                                                                       
  name: busybox1                                                                
  labels:                                                                       
    name: busybox                                                               
spec:                                                                           
  containers:                                                                   
  - name: busybox                                                               
    image: busybox                                                              
    command:                                                                    
    - sleep                                                                     
    - "3600"                                                                    
---                                                                             
apiVersion: v1                                                                  
kind: Pod                                                                       
metadata:                                                                       
  name: busybox2                                                                
  labels:                                                                       
    name: busybox                                                               
spec:                                                                           
  containers:                                                                   
  - name: busybox                                                               
    image: busybox                                                              
    command:                                                                    
    - sleep                                                                     
    - "3600"                                                                    

このマニフェストをデプロイして、先程作成したCentOSのコンテナで名前解決してみる。

# nslookup my-service
Server:     10.96.0.10
Address:    10.96.0.10#53

Name:   my-service.default.svc.cluster.local
Address: 172.17.0.4
Name:   my-service.default.svc.cluster.local
Address: 172.17.0.5

先程とは異なり、サービス名で名前解決すると、サービスのendpointとなっているPodのIPが返ってくる。これらがAレコードとして登録されているはず。 次に先程と同様にSRVレコードを確認してみる。

# nslookup -q=SRV _foo._tcp.my-service
Server:     10.96.0.10
Address:    10.96.0.10#53

_foo._tcp.my-service.default.svc.cluster.local  service = 10 50 5678 3237653666313939.my-service.default.svc.cluster.local.
_foo._tcp.my-service.default.svc.cluster.local  service = 10 50 5678 3139376166613530.my-service.default.svc.cluster.local.

各Podに適当なサブドメインが割り当てられてる。kube-dnsが勝手に付ける模様。そして、PortもServiceのPortではなく、Serviceで定義したtargetPortの値になってますね。まあ、これはPodのFQDNが各々返ってきてるので当然ですね。

ついでにPodのFQDNで名前解決してみる。

# nslookup 3237653666313939.my-service.default.svc.cluster.local
Server:     10.96.0.10
Address:    10.96.0.10#53

Name:   3237653666313939.my-service.default.svc.cluster.local
Address: 172.17.0.4

# nslookup 3139376166613530.my-service.default.svc.cluster.local
Server:     10.96.0.10
Address:    10.96.0.10#53

Name:   3139376166613530.my-service.default.svc.cluster.local
Address: 172.17.0.5

ちゃんとPodのIPが返ってきますね。

kubectlコマンドの補完を有効化する

kubectlコマンドはサブコマンドがあったり、オプションがあったりで覚えるのも入力するのも面倒。bash/zsh向けには補完する機能があるので、有効化してみた。Fedora27/bashの環境でのメモ。

$ cat /etc/redhat-release 
Fedora release 27 (Twenty Seven)
$ echo $SHELL
/bin/bash

まず、bash-completionパッケージが必要なのでインストール

$ sudo dnf install bash-completion

で、kubectl completionで補完する設定を吐き出してくれるので適当なファイルに吐き出して、bash_profileの中でsourceで読み込んであげればOK*1

$ kubectl completion bash > ~/.kube/completion.bash.inc
$ printf "
> # kubectl shell completion
> source '$HOME/.kube/completion.bash.inc'
> " >> $HOME/.bash_profile
$ source $HOEM/.bash?profile

これでkubectlの補完が有効になるはず。

minikueopenstackコマンドも同じようにして補完を有効にできますね。

*1:kubectl completion -hとかでやり方は確認可能

ConfigMapの使い方

Kubernetesを使う時、アプリの設定とかをコンテナイメージに埋め込むのではなく実行時に設定したい場合、ConfigMapを使う。

ConfigMapはkey-valueで情報を保持しているんだけど、これがなかなか便利で、ファイルから作る*1key: ファイル名value: ファイルの内容みたいに勝手にやってくれる*2ディレクトリから作る*3と、そのディレクトリに含まれるファイルを全部読み込んで、それぞれkey-valueとして保持してくれたりもする。

説明するより例の方が分かり易いので実際のコマンドで説明。

ConfigMapの定義

$ ls
redis-config

$ cat redis-config
maxmemory 2mb
maxmemory-policy allkeys-lru

であった時に、このファイルからConfigMapを作成してみると

$ kubectl create configmap <名前> --from-file=redis-config
configmap "<名前>" created

$ kubectl get configmap <名前>
apiVersion: v1
data:
  redis-config: |-
    maxmemory 2mb
    maxmemory-policy allkeys-lru
kind: ConfigMap
metadata:
  creationTimestamp: xxxxxxx
  name: <名前>
  namespace: default
  resourceVersion: "6872"
  selfLink: /api/v1/namespaces/default/configmaps/<名前>
  uid: 67b1ce21-125c-11e8-9a96-d4c7541dd274

のようになる。dataのところを見ると、ファイル名がキーになって、対応する内容がファイルの中身になっていることが確認できる。

ConfigMapの利用

ConfigMapに保存してある情報をPodで使う時は、ConfigMapの内容をファイルとして書き込んだvolumeを定義し、それをPodがmountして使う。

$ cat redis-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: kubernetes/redis:v1
    env:
    - name: MASTER
      value: "true"
    ports:
    - containerPort: 6379
    volumeMounts:
    - mountPath: /redis-master-data
      name: data
    - mountPath: /redis-master
      name: config
  volumes:
    - name: data
      emptyDir: {}
    - name: config
      configMap:
        name: example-redis-config
        items:
        - key: redis-config
          path: redis.conf

上記のように、volumeを定義するときに、ConfigMapを選び、keyでデータを、pathでボリューム内に作成するファイルを指定する。ここでは、redis.confというファイル(中身はConfigMap内のredis-configで指定したデータ)があるボリュームが作成される。Podではそれを/redis-masterディレクトリにマウントしていることから、Pod内ではConfigMapの内容は/redis-master/redis.confとして参照可能となる。

$ kubectl apply -f redis-pod.yaml
pod "redis" created

$ kubectl exec -it redis /bin/bash
root@redis:/data# ls /redis-master
redis.conf
root@redis:/data# cat /redis-master/redis.conf 
maxmemory 2mb
maxmemory-policy allkeys-lru

[参考]

kubernetes.io

*1:kubectl ... --from-file=でファイルを指定

*2:もちろんkeyをファイル名じゃなくて指定したものにすることも可能

*3:kubectl ... --from-file=でディレクトリを指定

FedoraにRictyフォントをインストール

基本的に本家に書いてある手順に従って実行していけばよいのだけど、補足メモを書いておく。

1. Rictyフォント生成スクリプトをダウンロード

こちらからricty_generator.shをダウンロード

$ mkdir Ricty
$ cd Ricty
$ wget http://www.rs.tus.ac.jp/yyusa/ricty/ricty_generator.sh

2. fontforgeをインストール

# dnf install -y fontforge

3. Inconsolataフォントをダウンロード

Google Fontsからダウンロード。

  • 右上のSELECT THIS FONTをクリック
  • 下にダブみたいのができるからクリック
  • 開いたウインドウ?の右上にダウンロードアイコンがあるのでダウンロード
  • ダウンロードしたzipファイルを先程作成したRictyディレクトリに解凍しておく

4. Migu 1Mフォントをダウンロード

こちらからダウンロード可能

  • ダウンロードしたzipファイルを先程作成したRictyディレクトリに解凍しておく

5. Rictyフォントの生成

$ cd Ricty
$ ./ricty_generator.sh auto

6. 作成されたフォントを/usr/share/fonts以下にコピー

# mkdir -p /usr/share/fonts/Ricty
# cp Ricty/Ricty* /usr/share/fonts/Ricty/

7. ターミナルのprofileやgnome-tweak-toolで利用するフォントを選択

pyenv/pyenv-virtualenv環境を構築する

必要なパッケージのインストール

pyenvはpythonをダウンロードしてきてコンパイルするけど、その際に必要となるパッケージを入れておく。Fedora以外はこちらを参照。

dnf install -y gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel xz

pyenvとpyenv-virtualenvのインストール

pyenv開発者がpyenv installerを公開しているのでそれを利用してインストールする。このインストーラがpyenv-virtualenvまで入れてくれるからラクチン。

$ curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
....
<snip>
...
WARNING: seems you still have not added 'pyenv' to the load path.

# Load pyenv automatically by adding
# the following to ~/.bash_profile:

export PATH="/home/hoge/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

ということなので、.bashrcに下記を追加しておく。

export PATH="/home/hoge/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

pythonのバージョンをインストールしてみる

インストール可能なバージョンを確認

$ pyenv install --list
...
3.6.4
...

特定バージョンのpythonをインストールする

$ python install 3.6.4
$ pyenv versions
* system (set by /home/hoge/.pyenv/version)
  3.6.4

新しい環境を作成してみる

システムのpythonのバージョンの確認

fedora 27のpythonのバージョンは2.7.14

$ python --version
Python 2.7.14

/home/hoge/hoge以下に3.6.4環境を作成してみる

$ cd /home/hoge/hoge
$ pyenv virtulenv 3.6.4 my_3.6.4
$ pyenv local my_3.6.4
$ python --version
Python 3.6.4
$ cd ..
$ python --version
Python 2.7.14

ということで、/home/hoge/hoge以下だけ3.6.4を使う環境をつくれた

起動失敗してgrubプロンプト(grub >)が出た場合の対処

調べるのが面倒なので、メモを残しておく。

1. パーティションの確認 (sda2から起動したい)

grub> ls
(hd0) (hd0,msdos3) (hd0,msdos2) (hd0,msdos1)

2. パーティションの中身の確認

grub> ls (hd0,msdos2)/
bin/ boot/ dev/ ....
grub> cat (hd0,msdos2)/etc/redhat-releases
Fedora release 27 (Twenty Seven)
grub> ls (hd0,msdos)/boot/
.... initramfs-4.14-11-300.fc27.x86_64.img .... vmlinuz-4.14.11-300.fc27.x86_64 ...

3. 起動

grub> set root=(hd0,msdos2)
grub> linux /boot/vmlinux-4.14.11-300.fc27.x86_64 root=/dev/sda2
grub> initrd /boot/initramfs-4.14.11-300.fc27.x86_64.img
grub> boot

4 (必要に応じて) grubの再インストール

# grub2-install /dev/sda

5 (必要に応じて) ファイルシステムの復旧

今回はxfsが壊れていたので下記コマンドを実行。

# xfs_repair /dev/sda2

参考

https://jp.linux.com/news/linuxcom-exclusive/418274-lco20140625 26.7. GRUB 2 の再インストール Red Hat Enterprise Linux 7 | Red Hat Customer Portal

psコマンドでプロセスの親子関係を表示する

今までps aux使ってたけど、f付けるだけで分かり易くなるの知らなかった。

$ ps auxf

​USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
​...

hoge 1981 0.0 0.1 534500 53764 tty2 S+ 23:19 0:00 \_ /opt/google/chrome/chrome --type=zygote
hoge 1982 0.0 0.0 148140 13112 tty2 S+ 23:19 0:00 | \_ /opt/google/chrome/nacl_helper
hoge 1985 0.0 0.0 534500 12308 tty2 S+ 23:19 0:00 | \_ /opt/google/chrome/chrome --type=zygote
hoge 2163 0.0 0.2 991548 83072 tty2 Sl+ 23:19 0:00 | \_ /opt/google/chrome/chrome --type=renderer --field-trial-handle=1715498460

...