VLAN間ルーティング(L3Switch)

CCNA取得からだいぶ経って、勉強した内容をほとんど忘れてしまったので、復習がてらにCisco Packet Tracerで以下の構成を組んでみました。

構成は、単純なL3Switchを用いたVLAN間ルーティングです。

以下、実際に入力した履歴です。

■Swtich-CW01

設定

Switch-CW01>

Switch-CW01>en

Switch-CW01#conf t

Enter configuration commands, one per line. End with CNTL/Z.

Switch-CW01(config)#int vlan 1

Switch-CW01(config-if)#ip address 192.168.100.5 255.255.255.0    <-マネジメントIP設定

Switch-CW01(config-if)#no shutdown

Switch-CW01(config-if)#exit

Switch-CW01(config)#ip routing    <-ルーティングの有効可

Switch-CW01(config)#vlan 10

Switch-CW01(config-vlan)#exit

Switch-CW01(config)#vlan 20

Switch-CW01(config-vlan)#exit

Switch-CW01(config)#int vlan 10

Switch-CW01(config-if)#ip address 192.168.1.254 255.255.255.0

Switch-CW01(config-if)#no shutdown

Switch-CW01(config-if)#exit

Switch-CW01(config)#int vlan 20

Switch-CW01(config-if)#ip address 192.168.2.254 255.255.255.0

Switch-CW01(config-if)#no shutdown

Switch-CW01(config-if)#exit

Switch-CW01(config)#int range g0/1-2    <-Switchportの確認

Switch-CW01(config-if-range)#switchport trunk encapsulation dot1q

Switch-CW01(config-if-range)#switchport mode trunk

Switch-CW01(config-if-range)#switchport trunk allowed vlan 10,20

Switch-CW01(config-if-range)#exit

 

設定確認

Switch-CW01#show vlan    <- Vlanの確認

 

VLAN Name Status Ports

---- -------------------------------- --------- -------------------------------

1 default active Fa0/1, Fa0/2, Fa0/3, Fa0/4

Fa0/5, Fa0/6, Fa0/7, Fa0/8

Fa0/9, Fa0/10, Fa0/11, Fa0/12

Fa0/13, Fa0/14, Fa0/15, Fa0/16

Fa0/17, Fa0/18, Fa0/19, Fa0/20

Fa0/21, Fa0/22, Fa0/23, Fa0/24

10 VLAN0010 active

20 VLAN0020 active

1002 fddi-default active

1003 token-ring-default active

1004 fddinet-default active

1005 trnet-default active

 

Switch-CW01#show int trunk    <- trunkポートの確認

Port Mode Encapsulation Status Native vlan

Gig0/1 on 802.1q trunking 1

Gig0/2 on 802.1q trunking 1

 

Port Vlans allowed on trunk

Gig0/1 10,20

Gig0/2 10,20

 

Port Vlans allowed and active in management domain

Gig0/1 10,20

Gig0/2 10,20

 

Port Vlans in spanning tree forwarding state and not pruned

Gig0/1 10,20

Gig0/2 10,20


 

Switch-CW01#show ip int brief    <-物理インタフェースとSVIの確認


FastEthernet0/22 unassigned YES unset down down

FastEthernet0/23 unassigned YES unset down down

FastEthernet0/24 unassigned YES unset down down

GigabitEthernet0/1 unassigned YES unset up up

GigabitEthernet0/2 unassigned YES unset up up

Vlan1 192.168.100.5 YES manual up down

Vlan10 192.168.1.254 YES manual up up

Vlan20 192.168.2.254 YES manual up up

 

 

■Switch01

Switch>

Switch>en

Switch#conf t

Enter configuration commands, one per line. End with CNTL/Z.

Switch(config)#hostname SW01

SW01(config)#int vlan 1

SW01(config-if)#ip address 192.168.100.1 255.255.255.0

SW01(config-if)#no shutdown

 

SW01(config-if)#

%LINK-5-CHANGED: Interface Vlan1, changed state to up

 

%LINEPROTO-5-UPDOWN: Line protocol on Interface Vlan1, changed state to up

 

SW01(config-if)#exit

SW01(config)#vlan 10

SW01(config-vlan)#exit

SW01(config)#vlan 20

SW01(config-vlan)#exit

SW01(config)#int range fa0/1-2

SW01(config-if-range)#switchport mode access

SW01(config-if-range)#int fa0/1

SW01(config-if)#switchport access vlan 10

SW01(config-if)#int fa0/2

SW01(config-if)#switchport access vlan 20

 

SW01(config-if)#int g0/1

SW01(config-if)#switchport mode trunk

SW01(config-if)#switchport trunk allowed vlan 10,20

SW01(config-if)#exit

SW01(config)#exit

SW01#

 

 

■Switch02

Switch>

Switch>en

Switch#conf t

Enter configuration commands, one per line. End with CNTL/Z.

Switch(config)#hostname SW02

SW02(config)#int vlan 1

SW02(config-if)#ip address 192.168.100.2 255.255.255.0

SW02(config-if)#no shutdown

 

SW02(config-if)#

%LINK-5-CHANGED: Interface Vlan1, changed state to up

 

%LINEPROTO-5-UPDOWN: Line protocol on Interface Vlan1, changed state to up

 

SW02(config-if)#exit

SW02(config)#vlan 10

SW02(config-vlan)#exit

SW02(config)#vlan 20

SW02(config-vlan)#exit

SW02(config)#int range fa0/1-2

SW02(config-if-range)#switchport mode access

SW02(config-if-range)#int fa0/1

SW02(config-if)#switchport access vlan 10

SW02(config-if)#int fa0/2

SW02(config-if)#switchport access vlan 20

 

SW02(config-if)#int g0/1

SW02(config-if)#switchport mode trunk

SW02(config-if)#switchport trunk allowed vlan 10,20

SW02(config-if)#exit

SW02(config)#exit

SW02#

 

 

PC0(192.168.1.1)からPC3(192.168.2.2)に問題なく疎通とれることを確認できました。

仕事でネットワークを触ることがほとんどないので、時間があるタイミングで今後もやったことをアップしていきたいと思います。

Slack API を用いた容量監視

概要

awxサーバの容量がひっ迫してサーバがダウンする事象が発生していたため、 毎週月曜日に容量を取得しSlackに投稿するボットを作りました

手順

  1. slack apiのenableとスレッド指定
  2. slack webhook urlの取得
  3. python スクリプトの作成
  4. cronの設定

結果

1. slack apiのenableとスレッド指定

※下記を参考に設定
https://api.slack.com/messaging/webhooks#getting_started

2. slack webhook urlの取得

1の設定後に下記のようなwebhook urlを取得できる
https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXXXXX

3. python スクリプトの作成

2で取得したwebhook url宛にリクエスト(post)を投げるスクリプトを作成。
ルートディレクトリの容量はsubprocessモジュールを使用して取得。
※dataの書き方は少し独特なので、もしトラブった場合は以下を参照。
formatを使用した文字列内で波括弧({)を使用する

import requests
import subprocess, sys
import socket


def create_message():
    hostname = socket.gethostname()
    cap = subprocess.run('df -h /', shell=True, encoding='utf-8', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    if cap.returncode != 0:
        cap_msg = "error"
    else:
        cap_msg = cap.stdout

    message = f"[{hostname}]\n {cap_msg}"
    return message


def post_message(message):
    headers = {
        "Content-type": "application/json"
    }

    data = f'{{"text":"{message}"}}'

    response = requests.post('https://hooks.slack.com/services/XXXXXXX', headers=headers, data=data) # 2で取得したwebhook urlを指定


def main():
    message = create_message()
    post_message(message)


if __name__ == '__main__':
    main()

実際にSlackに送られたメッセージ

[centos7]
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root  104G   22G   82G  21% /

curlでもテスト

curl -i -H "Content-type: application/json" -s -S -X POST -d '{"text":"test"}' https://hooks.slack.com/services/XXXXXX

問題なく「test」というメッセージが送られてきました。

4. cronの設定

毎週月曜日に容量を確認
$crontab -e

0 9 * * 1 python /root/slackapp/post_message_to_slack.py

参照

https://qiita.com/momotaro98/items/fe567041cbd2bd3f2281 https://api.slack.com/messaging/webhooks#getting_started

formatを使用した文字列内で波括弧({)を使用する

概要

python で format を使う場合に、文字列内で波括弧({)を使う場合は波括弧({)を重ねる必要がある。

事象

Slack APIを使う際にdataの文字列に波括弧({)を入れる必要があった。また、文字列には変数も展開する必要があったので、 formatを使い、以下のように書いていたが、その場合pep8でも引っかかり、また、プログラムもエラーとなった。

data = f'{"text": "{message}"}'

実行時のエラー

'...'.format(...) has unused arguments at position(s): 0
'...'.format(...) is missing arguments(s) for placeholder(s):

解決策

formatを使った文字列内で、そのまま波括弧({)を表示されたい場合は、波括弧({)を重ねて "{{" とする。

data = '{{"text": "{}"}}'.format("message")
# data: {"text": "{}"}

また、Pythonのバージョン3.6から追加されたfを使うと以下のようになる。

data = f'{{"text":"{message}"}}'

is bool は template error while templating string

概要

プレイブックのwhen文でis trueを使っていたところ、ansible 2.10.5では動いていたが ansible-core 2.11.0rc2 で動かなくなった。 ※3/26時点の最新バージョンである2.12.3でも同様の結果

事象

ansible 2.10.5では動いていた以下のプレイブックがansibleをバージョンアップした所、動かなくなった。

- hosts: localhost
  name: Test
  connection: local
  gather_facts: False
  vars:
    b: True

  tasks:
  - name: Test
    debug:
      msg: "test"
    when: b is True

動かなかった時のエラー内容

fatal: [localhost]: FAILED! => {"msg": "The conditional check 'b is True' failed. The error was: template error while templating string: no test named 'True'. String: {% if b is True %} True {% else %} False {% endif %}\n\nThe error appears to be in ... : line 18, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n  - name: Test\n    ^ here\n"}

おそらく、いつのバージョンからか is bool という書き方がサポートされなくなったと思われる。

解決策

== True(もしくは、比較の部分の記載を消して変数だけにする)
  ※冗長だけど、自分的には==Trueなどの記載があった方が分かりやすくて好き

そのため、以下のように変更したところ、問題なく動いた。

- hosts: localhost
  name: Test
  connection: local
  gather_facts: False
  vars:
    b: True

  tasks:
  - name: Test
    debug:
      msg: "test"
    when: b == True

Ansible extra-varsで真偽値(True/False)を使う

概要

ansibleの実行時にextra-varsで変数の真偽値(True/False)を変更する場合、 そのまま指定しても変更できません。

参考

例えば、以下のように実行すると、test_boolに"True"という文字列が入るため、 真偽値のTrueのような使い方は出来ません。

$ ansible-playbook exstra_vars_boolean.yml -e test_bool=true

解決策

extra-varsで値を辞書型で宣言すれば、真偽値をアップデートできます。

$ ansible-playbook exstra_vars_boolean.yml -e '{"test_bool": True}'

実行例

# exstra_vars_boolean.yml
---
- hosts: localhost
  gather_facts: no
  vars:
    test_bool: false
  tasks:
    - name: debug test_bool
      debug: var=test_bool
      when: test_bool == True

上記のymlを実行する場合、下記のように実行することで、test_boolの値をアップデート出来る

$ ansible-playbook exstra_vars_boolean.yml -e '{"test_bool": True}'
PLAY [localhost] *************************************************************************

TASK [debug test_bool] *******************************************************************
ok: [localhost] => {
    "test_bool": true
}

PLAY RECAP *******************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

kubeadm ノードの追加

kubeadmのクラスターで新規ノードを追加したときの備忘録。

公式サイト

一般的にはコントロールプレーンノードでkubeadm initをしたときに出力されるkubeadm initを実行すれば良い

kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>

ただ、それを記録していなかった場合、24時間以内であれば、次のコマンドで<token>を取得可能

kubeadm token list

24時間たってしまい、上記で取得できない場合は、次のコマンドで新しいトークンを作成する必要がある。

kubeadm token create

--discovery-token-ca-cert-hash sha256:<hash>の値は、コントロールプレーンノードで次のコマンドチェーンを実行することで取得可能

openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
   openssl dgst -sha256 -hex | sed 's/^.* //'

実際に実行した結果

既存のクラスタ(kube01: master, kubeadm02: worker)にkubeadm03: workerを追加する

作業前の状態

[root@kube01 ~]# k get node
NAME        STATUS   ROLES                  AGE     VERSION
kube01      Ready    control-plane,master   7d18h   v1.21.0
kubeadm02   Ready    <none>                 7d18h   v1.21.0

トークンの作成

[root@kube01 ~]# kubeadm token list #何も表示されなかった場合、createを実施
[root@kube01 ~]# kubeadm token create
a2fybd.2j7fvqa71urarpl2

ca-certのハッシュ値確認

[root@kube01 ~]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
>    openssl dgst -sha256 -hex | sed 's/^.* //'
4ea2ed8b2642a06bcf4f9117e33b590b9d5e3209ba5ba2aec3e9e5326fe179c8

ipアドレスの確認

[root@kube01 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:8d:c4:88 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.249/24 brd 192.168.1.255 scope global noprefixroute ens192
       valid_lft forever preferred_lft forever
    inet6 fe80::b56b:899e:2c88:ab13/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
…

kubeadm03でkubeadm joinの実行(デフォルトの<control-plane-port>は6443)

[root@kubeadm03 ~]# kubeadm join --token a2fybd.2j7fvqa71urarpl2 192.168.1.249:6443 --discovery-token-ca-cert-hash sha256:4ea2ed8b2642a06bcf4f9117e33b590b9d5e3209ba5ba2aec3e9e5326fe179c8
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

kubeadm03が追加されたことを確認

[root@kube01 ~]# k get nodes
NAME        STATUS     ROLES                  AGE     VERSION
kube01      Ready      control-plane,master   7d18h   v1.21.0
kubeadm02   Ready      <none>                 7d18h   v1.21.0
kubeadm03   NotReady   <none>                 7s      v1.21.0
[root@kube01 ~]# k get nodes
NAME        STATUS   ROLES                  AGE     VERSION
kube01      Ready    control-plane,master   7d18h   v1.21.0
kubeadm02   Ready    <none>                 7d18h   v1.21.0
kubeadm03   Ready    <none>                 13s     v1.21.0

mysql: unknown option &#39;--&quot;&#39; エラー

概要

KubernetesMysqlコンテナ(mysql:5.6) を動かそうと思ったら、
コンテナがunknown option '--"'で止まってしまいました。

原因

原因はMysql環境変数に設定しているsecretの作成時、 echo に -n オプションをつけていなかったからでした。

解決策

base64エンコードするとき以下のようにechoに-nをつければ解決するはずです。

$ echo -n password | base64
cGFzc3dvcmQ=

参考

エラーが起きた時のスクリーンショット f:id:masa111111:20220219074503p:plain f:id:masa111111:20220219074642p:plain

mysqlコンテナの作成に使用したymlファイル(wordpress向け)

#secret.yml
apiVersion: v1
kind: Secret
metadata:
  name: wp-auth
data:
  WORDPRESS_DB_HOST: d29yZHByZXNzLW15c3Fs #wordpress-mysql
  WORDPRESS_DB_PASSWORD: cGFzc3dvcmQ= #password

  MYSQL_ROOT_PASSWORD: cGFzc3dvcmQ= #password
#mysql.yml
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
  labels:
    app: wordpress
spec:
  accessModes: 
  - ReadWriteOnce
  capacity:
    storage: 10G 
  hostPath:
    path: /home/uniuser/wordpress/mysql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  serviceName: mysql
  replicas: 1
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        envFrom:
        - secretRef:
            name: wp-auth
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim