- ã¯ããã«
- FireLens ã®æ§æ
- ãã°æ失ã®åé¿çã®èª²é¡
- init ãå©ç¨ãã INPUT ã®è¨å®ã®ã«ã¹ã¿ãã¤ãºã«ãã解決ç
- ãããã«
- ã«ã¹ã¿ã init ã®ã½ã¼ã¹ã³ã¼ã
ã¯ããã«
AWS FireLens ã¯ãAmazon ECS ã§åä½ããã³ã³ãããåºåãããã°ããFluentBit ã¾ã㯠Fluentd ã使ã£ã¦æè»ã«ã«ã¼ãã£ã³ã°ããããã®ä»çµã¿ã§ããç¹ã«ãã¿ã¹ã¯å®ç¾©ã®ã¿ã§ãã°ã«ã¼ãã£ã³ã°ã®è¨å®ãå¯è½ãªãããæ§æ管çãã·ã³ãã«ã«ã§ããç¹ãç¹å¾´ã¨ãªã£ã¦ãã¾ãã
ãããã大éã®ãã°ãæ¬ æãªãæ±ãããã«è¨å®ã®èª¿æ´ãè¡ããã¨æã£ã¦ããç¾ç¶ã®æ©è½ã§ã¯ä¸çç¸ã§ã¯ãããªããã¨ãããã¾ãã
ãã®è¨äºã§ã¯ FireLens ã®å©ä¾¿æ§ãæ´»ãããã¾ã¾èª¿æ´ãå¯è½ã«ããæ¹æ³ããç´¹ä»ãã¾ãã
FireLens ã®æ§æ
FireLens ã¯ä»¥ä¸ã®2ã¤ã®è¦ç´ ããæ§æããã¦ããã¨ããã¾ãã
- awsfirelens ãã°ãã©ã¤ãã¼
- FluentBitã»Fluentd ã® config çææ©è½

awsfirelens ãã°ãã©ã¤ãã¼
ã¿ã¹ã¯å®ç¾©ä¸ã«ã以ä¸ã®ããã« logDriver ã¨ã㦠"awsfirelens" ãæå®ãã¾ããããã¯æ¬ç©ã®ãã°ãã©ã¤ãã¼ã§ã¯ãªããå®éã«ã¯ Docker Fluentd ãã°ãã©ã¤ãã¼ã使ã£ã¦ããã®ã³ã³ããã®æ¨æºåºåã»æ¨æºã¨ã©ã¼åºåã FluentBitã»Fluentd ã³ã³ããã« UNIX Domain Socket (/var/run/fluent.sock)çµç±ã§éãã¾ãã
ã¾ã options ã¨ãã¦ããã®ãã°ãéãããå
ã®è¨å®ãè¨è¿°ãã¾ãããããã¯æ¬¡ç¯ã®æ©è½ã§åç
§ããã¾ãã
"logConfiguration": { "logDriver": "awsfirelens", "options": { "Name": "s3", "region": "ap-northeast-1", "bucket": "...", ... } }
FluentBitã»Fluentd ã® config çææ©è½
FireLens èªä½ã¯ FluentBitã»Fluentd ã¯æä¾ãã¾ããã代ããã«ã¿ã¹ã¯å®ç¾©ã« FluentBitã»Fluentd ã³ã³ãããå«ãã¦ããå¿
è¦ãããã¾ããããã¦ä»¥ä¸ã®è¨å®ã追å ããã¨ããã®ã³ã³ããã FireLens ã®éãå
ã¨ãªãã¾ãã
FireLens ã¯ãåç¯ã®ä¾ã®ãããªä»ã®ã³ã³ããã® logConfiguration.options ã«å¾ã£ã¦ããã°ãæ¯ãåããããã® FluentBitã»Fluentd ã®è¨å®ãã¡ã¤ã«ãçæããããã FluentBitã»Fluendã³ã³ããå
ã®ããã©ã«ãè¨å®ãã¡ã¤ã«ã®ãã¹ã« read-only ãã¦ã³ããã¾ãã
ãã®æã以ä¸ã®ããã« options 㧠S3 ãã³ã³ããå ã®ãã¡ã¤ã«ãã追å ã® config ãèªã¿è¾¼ã¾ããï¼ FluentBit ãªã @INCLUDE ãã£ã¬ã¯ãã£ãã追å çæããã ï¼ãã¨ãå¯è½ã§ããããã«ãã£ã¦ãç¹å®æ¡ä»¶ã«ããããããã°ãæ½åºãã¦å¥ã®ã¨ããã«éä¿¡ããããã¢ããªã±ã¼ã·ã§ã³ç¬èªã§ TCP port 24224 ã«éã£ããã°ãä¸ç·ã«ã«ã¼ãã£ã³ã°ããããã¨ãã§ãã¾ãã
"firelensConfiguration": { "type": "fluentbit" "options": { "config-file-type": "s3", "config-file-value": "arn:aws:s3:::mybucket/fluent.conf" } }
ä¸è¨ã®è¨å®ã®å ´åã FireLens ã¯ä»¥ä¸ã®ãã㪠FluentBit è¨å®ãã¡ã¤ã«ãçæãã¾ãã
[INPUT] Name tcp Listen 127.0.0.1 Port 8877 Tag firelens-healthcheck [INPUT] Name forward unix_path /var/run/fluent.sock [INPUT] Name forward Listen 127.0.0.1 Port 24224 @INCLUDE /fluent-bit/etc/extra.conf [OUTPUT] Name null Match firelens-healthcheck [OUTPUT] Name s3 Match <ã³ã³ããå>-firelens* bucket ... region ap-northeast-1 ...
extra.conf ã¨ã㦠S3 ããåå¾ãã追å è¨å®ãèªã¿è¾¼ãã§ãã¾ãããã®æ©è½ã®ãããã§äºåã« FluentBitã»Fluentd ã³ã³ããã¤ã¡ã¼ã¸ã«è¨å®ãæ ¼ç´ãã¦ããå¿ è¦ããªããªãã FluentBit ã¤ã¡ã¼ã¸ã¨ã㦠Docker Hub çã§é å¸ããã¦ãããªãã£ã·ã£ã«ã®ãã®ã AWS ãç¨æãã¦ãã FireLens ç¨ã¤ã¡ã¼ã¸ããã®ã¾ã¾ä½¿ç¨ã§ãã¾ãã
ãã°æ失ã®åé¿çã®èª²é¡
以ä¸ã§ã¯ FluentBit ã使ããã¨ãåæã¨ãã¾ãã
FireLens ã®çæãã INPUT ã«ã¯ãªãã·ã§ã³ã¯ç¹ã«è¨å®ããã¦ãããã FluentBit ã®ããã©ã«ãè¨å®ã使ç¨ããã¾ãããã®å ´åãåãåã£ããã°ã¯ä¸åº¦ã¡ã¢ãªä¸ã®ãããã¡ã«æ ¼ç´ãããä¸å®æéãã¨ã«åºåå
ã«éä¿¡ï¼Flushï¼ããã¾ãããã®ãã極ãã¦å¤§éã®ãã°ãåãåãã¨ã¡ã¢ãªä¸è¶³ã«ãªããã¨ãããããã°ã®ä¸é¨ãæ¬ æãããã¨ãããã¾ãã
以ä¸ã® AWS ããã° ã§ãã大éã®ãã°ãå¦çããå ´åã«ãã°ãæ¬ æããä¾ããããFlush ééã調æ´ã§æ¹åã試ã¿ã¦ãã¾ãã
aws.amazon.com
ãã®ä¸ã§ãããæ ¹æ¬çãªæ¹åã®ããã«ãINPUT ã«ã¡ã¢ãªãããã¡ãµã¤ãºãå¶éãã Mem_Buf_Limit ãªãã·ã§ã³ã追å è¨å®ãããã¨ãããªã¯ã¨ã¹ããåºããã¦ãã¾ããããããç¾ç¶ FireLens èªä½ã«ã¯ãã®ããã®è¨å®æ¹æ³ãããã¾ããã
ããã§ãå®å
¨ã« fluent-bit.conf ãç½®ãæãããã¨ã§ãªãã·ã§ã³æå®ãè¡ãæ¹æ³ã®ä¾ã AWS ã® GitHub ã§å
¬éããã¦ãã¾ãã
github.com
ãã ããã®æ¹æ³ã§ã¯ FireLens ãçæããè¨å®ãã¡ã¤ã«ãç¡è¦ããã¦ãããããã¿ã¹ã¯å®ç¾©ã ãã§ãã°ã«ã¼ãã£ã³ã°ãã§ããã¨ããæ©è½ã失ããã¦ãã¾ãæ¬ ç¹ãããã¾ãã
ç¹ã«ãã²ã¼ã ã®éçºç°å¢ã§ã¯ä¼¼ããããªç°å¢(ECSã¿ã¹ã¯)ãè¤æ°ããããã¤ç°å¢ãã¨ã«ãã°ã®åºåå
ãåãããã¨ãããã¼ãºããããããç°å¢å¥ã® FluentBit ã¤ã¡ã¼ã¸ãç¨æããªããã°ãªããªãã¨ãªãã¨éç¨ã大å¤ã«ãªãã¨ãã課é¡ãããã¾ãã*1ã
init ãå©ç¨ãã INPUT ã®è¨å®ã®ã«ã¹ã¿ãã¤ãºã«ãã解決ç
æ¢åæ©è½ã§ã§ããã㪠INPUT ã®ã«ã¹ã¿ãã¤ãºæ¹æ³ã¨ãã¦ã追å è¨å®ãã¡ã¤ã«ã« INPUT ã»ã¯ã·ã§ã³ãæ¸ãã¦ããã¨ãããã®ãèãããã¾ãã
[INPUT] Name forward unix_path /var/run/fluent.sock # 追å storage.type filesystem [INPUT] Name forward Listen 127.0.0.1 Port 24224 # 追å storage.type filesystem ...(ãã®ä»ã®ã«ã¹ã¿ã ãã°ã«ã¼ãã£ã³ã°è¨å®ãªã©ãç¶ã)
ããã INPUT ã追è¨ããã ãã§ã¯ãFireLensãçæãã INPUT ã¨ã®TCPãã¼ãéè¤ã«ãããã¨ã©ã¼ã§ FluentBit ãæ£å¸¸ã«èµ·åããªããªã£ã¦ãã¾ãã¾ãã
ããã解決ãããããã³ã³ããã® init ããã»ã¹ãå©ç¨ãã¦è¨å®ãã¡ã¤ã«ãå å·¥ããã¨ããæ¹æ³ãç´¹ä»ãã¾ãã
AWS ã® FireLens ç¨ã³ã³ããã®ã½ã¼ã¹ãè¦ãã¨ãinit プロセスを利用して複数の追加設定を S3 から取得する機能を追加したイメージãããã¾ãããããåèã«ã以ä¸ã®ãããªå¦çããã init ããã»ã¹ã Go ã§ä½æãã¾ããã
- è¨å®ãã¡ã¤ã«ã« @INCLUDE ãããããã®ä¸ã§ forward INPUT ãå®ç¾©ãã¦ããå ´åãå ã®è¨å®ãã¡ã¤ã«ããããã¨éè¤ãã port ã unix_path ãæ㤠INPUT è¨å®ãåé¤ãã *2
- æ´æ°ããè¨å®ãã¡ã¤ã«ãæå®ã㦠FluentBit ã exec ã§èµ·åãã *3
è¦ã¯ãéè¤ã§ã¨ã©ã¼ã«ãªããªãããã®é¨åãåé¤ãã¦ä¸ã¤ã«ãã¦ããã°è¯ãã¨ãããã¨ã§ããã
ãªã Go ãé¸ãã ã®ã¯ FluentBit ã¤ã¡ã¼ã¸ã®ä¸ã«ã¯ /bin/sh ããå«ã¾ãã¦ããªããããã·ã³ã°ã«ãã¤ããªã§åä½ããå¿
è¦ããããã¨ãçç±ã®ä¸ã¤ã§ã*4ã ã½ã¼ã¹ã³ã¼ãã¯æ¬è¨äºã®æ«å°¾ã«ããã¾ãã
ãã¨ã¯ããããã«ãã㦠Docker ã¤ã¡ã¼ã¸ã«è¿½å ãã ENTRYPOINT ã¨ãã¦æå®ããã°æºåå®äºã§ãã
ãã«ã:
# aarch64 ã¢ã¼ããã¯ãã£ç¨ã¨ããå ´å GOOS=linux GOARCH=arm64 go build -o init init.go
Dockerfile:
FROM fluent/fluent-bit:3.1 COPY fluent-bit/init/init /opt/init ENTRYPOINT ["/opt/init"]
ãã㧠FireLens ãçæãã INPUT ã追å è¨å®ã«ä¸æ¸ããããããã«ãªã£ãã®ã§ãä¸è¨ã®ä¾ã®ããã« INPUT ã»ã¯ã·ã§ã³ã追å è¨å®ã«æ¸ããã¨ã§ãªãã·ã§ã³ãã«ã¹ã¿ãã¤ãºã§ããããã«ãªãã¾ããã
ãããã«
æ¬è¨äºã§ã¯ãFireLens ã®ã¿ã¹ã¯å®ç¾©ã«ãããã°ã«ã¼ãã£ã³ã°ãçãããã¾ã¾ã FluentBit ã³ã³ããèµ·åæã« init 㧠FireLens ãçæããè¨å®ãã¡ã¤ã«ãå å·¥ãããã¨ã§ INPUT ã®è¨å®ãã«ã¹ã¿ãã¤ãºã§ããããã«ããæ¹æ³ãç´¹ä»ãã¾ããã
AWS ã® GitHub ã«ç¤ºãããæ¹æ³ã§ã¯ã«ã¹ã¿ãã¤ãºã®ããã«ãã£ããã® FireLens ã®è¨å®ãã¡ã¤ã«çææ©è½ãç¡å¹åãã¦ãã¾ã£ã¦ãã¾ããããä»åã®æ¹æ³ã§ããã°ä½µç¨ãå¯è½ã§ãã(ãã¼ãºã¯èªèããã¦ããããªã®ã§ãä»å¾ FireLens ã®æ¨æºæ©è½ã§ INPUT ã®ãªãã·ã§ã³ãè¨å®ã§ããããã«ãªãã¨è¯ãã®ã§ããâ¦ã)
ãªãä½è«ã§ãããå°ãåã« ECS ã« RestartPolicy ã追å ãããFluentBit ã®ã³ã³ãããç°å¸¸çµäºããå ´åã«ã¿ã¹ã¯å ¨ä½ã¯èµ·åããã¾ã¾ã³ã³ããåä½ã§åèµ·åããããã¨ãå¯è½ã«ãªãã¾ããããã® RestartPolicy ãæå¹åããä»åã®æ¹æ³ã§ INPUT ã« filesystem storage ãå©ç¨ãã¦ãããã¡ã Volume ã«ç½®ãã°ãåèµ·åå¾ã«ãã°ãåéããããã¨ãã§ãããããã°ã®ä¿¡é ¼æ§ãåä¸ããããããã§ãã
ã«ã¹ã¿ã init ã®ã½ã¼ã¹ã³ã¼ã
package main // Init for FireLens Fluent Bit container // This removes `forward` input sections from the main Fluent Bit configuration file // if they are already defined in additional config files specified by @INCLUDE directives. // This is a workaround for the limitation that FireLens does not currently support customizing input options. import ( "fmt" "io/ioutil" "os" "strings" "syscall" ) const ( defaultConfigPath = "/fluent-bit/etc/fluent-bit.conf" defaultBinaryPath = "/fluent-bit/bin/fluent-bit" ) func nextSection(lines []string) ([]string, []string) { for i, line := range lines[1:] { if strings.HasPrefix(line, "[") || strings.HasPrefix(line, "@") { return lines[:i+1], lines[i+1:] } } return lines, nil } func getForwardBindInSection(section []string) string { if len(section) > 0 && strings.TrimSpace(section[0]) == "[INPUT]" { isForward := false bind := "" for _, line := range section[1:] { fields := strings.Fields(strings.ToLower(line)) if len(fields) < 2 { continue } if fields[0] == "name" && fields[1] == "forward" { isForward = true } if fields[0] == "port" || fields[0] == "unix_path" { bind = fields[1] } } if isForward { return bind } } return "" } func addIncludedForwards(includedFile string, includedForwards map[string]string) { contentBytes, err := ioutil.ReadFile(includedFile) if err != nil { panic(err) } content := string(contentBytes) lines := strings.Split(content, "\n") for lines != nil { var section []string section, lines = nextSection(lines) bind := getForwardBindInSection(section) if bind != "" { includedForwards[bind] = includedFile } } } func updateConfigFile(configPath string) { contentBytes, err := ioutil.ReadFile(configPath) if err != nil { panic(err) } content := string(contentBytes) lines := strings.Split(content, "\n") configLines := make([]string, 0) includedForwards := make(map[string]string) for _, line := range lines { if strings.HasPrefix(strings.ToLower(line), "@include ") { includedFile := strings.TrimSpace(line[9:]) addIncludedForwards(includedFile, includedForwards) } } for lines != nil { var section []string section, lines = nextSection(lines) bind := getForwardBindInSection(section) if bind != "" && includedForwards[bind] != "" { fmt.Printf("Skipping forward input for '%s' because it is already included in '%s'\n", bind, includedForwards[bind]) continue } configLines = append(configLines, section...) } file, err := os.OpenFile(configPath+".new", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { panic(err) } defer file.Close() file.WriteString(strings.Join(configLines, "\n")) fmt.Println("Generated new config file", configPath+".new") } func executeFluentBit(configPath string, binaryPath string) { args := []string{binaryPath, "-c", configPath + ".new"} err := syscall.Exec(binaryPath, args, os.Environ()) if err != nil { panic(err) } } func main() { updateConfigFile(defaultBinaryPath) executeFluentBit(defaultBinaryPath, defaultBinaryPath) }
*1:ç°å¢å¤æ°ã§é å¼µãæ¹æ³ãèãããããã§ãããç°å¢éã§ã³ã³ããæ§æçã«å¤å°éãããã£ãããããããFireLens ãããè¤é度ã¯ä¸ããããã§ãã
*2:å ã®èª¬æã®ããã«å ã®è¨å®ãã¡ã¤ã«ã¯ read only ãã¦ã³ãããã¦ããæ¸ãæãããã¨ã¯ã§ãã¾ããã®ã§ãæ°ãããã¡ã¤ã«ãä½æãã¦ããã«æ¸ãåºãã¦ãã¾ãã
*3:exec ãããã¨ã§ fluent-bit ããã»ã¹ã PID 1 ã¨ãã¦ãã³ã³ããåæ¢æã«TERMã·ã°ãã«ãæ£ããåãåããããã«ãã¾ãã
*4:ãã®ãããããã°ã®éã¯ä»ãã¤ããªãå«ã debug ãã¿ã°ã«å«ã¾ããã¤ã¡ã¼ã¸ã使ãã¨ãã Docker Debug ã使ãã¨ãã£ãå¿ è¦ãããã¾ãã