logging
This commit is contained in:
@ -19,6 +19,8 @@ module.exports = {
|
||||
['link', {rel: "stylesheet", href: "/java-script-dist/swiper-4.5.0/css/swiper.min.css"}],
|
||||
['script', {src: '/java-script-dist/swiper-4.5.0/js/swiper.min.js'}],
|
||||
// ['script', {type: 'text/javascript', src: 'https://tajs.qq.com/stats?sId=66467492', charset: 'UTF-8'}]
|
||||
['script', { 'data-ad-client': "ca-pub-3313149841665250", async: true, src: "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"}],
|
||||
// <script data-ad-client="ca-pub-3313149841665250" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
],
|
||||
markdown: {
|
||||
toc: { includeLevel: [2, 3] },
|
||||
|
||||
1
.vuepress/public/images/search.svg
Normal file
1
.vuepress/public/images/search.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#aaa" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg>
|
||||
|
After Width: | Height: | Size: 216 B |
@ -0,0 +1,38 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: counter
|
||||
spec:
|
||||
containers:
|
||||
- name: count
|
||||
image: busybox
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- >
|
||||
i=0;
|
||||
while true;
|
||||
do
|
||||
echo "$i: $(date)" >> /var/log/1.log;
|
||||
echo "$(date) INFO $i" >> /var/log/2.log;
|
||||
i=$((i+1));
|
||||
sleep 1;
|
||||
done
|
||||
volumeMounts:
|
||||
- name: varlog
|
||||
mountPath: /var/log
|
||||
- name: count-log-1
|
||||
image: busybox
|
||||
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log']
|
||||
volumeMounts:
|
||||
- name: varlog
|
||||
mountPath: /var/log
|
||||
- name: count-log-2
|
||||
image: busybox
|
||||
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/2.log']
|
||||
volumeMounts:
|
||||
- name: varlog
|
||||
mountPath: /var/log
|
||||
volumes:
|
||||
- name: varlog
|
||||
emptyDir: {}
|
||||
283
.vuepress/theme/components/BdSearchBox.vue
Normal file
283
.vuepress/theme/components/BdSearchBox.vue
Normal file
@ -0,0 +1,283 @@
|
||||
<template>
|
||||
<div class="search-box">
|
||||
<input
|
||||
id="bdcsMain"
|
||||
@input="query = $event.target.value"
|
||||
aria-label="Search"
|
||||
:value="query"
|
||||
:class="{ 'focused': focused }"
|
||||
:placeholder="placeholder"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
@keyup.enter="go(focusIndex)"
|
||||
@keyup.up="onUp"
|
||||
@keyup.down="onDown"
|
||||
ref="input"
|
||||
>
|
||||
<ul
|
||||
class="suggestions"
|
||||
v-if="showSuggestions"
|
||||
:class="{ 'align-right': alignRight }"
|
||||
@mouseleave="unfocus"
|
||||
>
|
||||
<li
|
||||
class="suggestion"
|
||||
v-for="(s, i) in suggestions"
|
||||
:class="{ focused: i === focusIndex }"
|
||||
@mousedown="go(i)"
|
||||
@mouseenter="focus(i)"
|
||||
>
|
||||
<a :href="s.path" @click.prevent>
|
||||
<span class="page-title">{{ s.title || s.path }}</span>
|
||||
<span v-if="s.header" class="header">> {{ s.header.title }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* global SEARCH_MAX_SUGGESTIONS, SEARCH_PATHS, SEARCH_HOTKEYS */
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
query: '',
|
||||
focused: false,
|
||||
focusIndex: 0,
|
||||
placeholder: undefined
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.placeholder = this.$site.themeConfig.searchPlaceholder || ''
|
||||
document.addEventListener('keydown', this.onHotkey)
|
||||
},
|
||||
|
||||
beforeDestroy () {
|
||||
document.removeEventListener('keydown', this.onHotkey)
|
||||
},
|
||||
|
||||
computed: {
|
||||
showSuggestions () {
|
||||
return (
|
||||
this.focused
|
||||
&& this.suggestions
|
||||
&& this.suggestions.length
|
||||
)
|
||||
},
|
||||
|
||||
suggestions () {
|
||||
const query = this.query.trim().toLowerCase()
|
||||
if (!query) {
|
||||
return
|
||||
}
|
||||
|
||||
const { pages } = this.$site
|
||||
const max = this.$site.themeConfig.searchMaxSuggestions || SEARCH_MAX_SUGGESTIONS
|
||||
const localePath = this.$localePath
|
||||
const matches = item => (
|
||||
item
|
||||
&& item.title
|
||||
&& item.title.toLowerCase().indexOf(query) > -1
|
||||
)
|
||||
const res = []
|
||||
for (let i = 0; i < pages.length; i++) {
|
||||
if (res.length >= max) break
|
||||
const p = pages[i]
|
||||
// filter out results that do not match current locale
|
||||
if (this.getPageLocalePath(p) !== localePath) {
|
||||
continue
|
||||
}
|
||||
|
||||
// filter out results that do not match searchable paths
|
||||
if (!this.isSearchable(p)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (matches(p)) {
|
||||
res.push(p)
|
||||
} else if (p.headers) {
|
||||
for (let j = 0; j < p.headers.length; j++) {
|
||||
if (res.length >= max) break
|
||||
const h = p.headers[j]
|
||||
if (matches(h)) {
|
||||
res.push(Object.assign({}, p, {
|
||||
path: p.path + '#' + h.slug,
|
||||
header: h
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
},
|
||||
|
||||
// make suggestions align right when there are not enough items
|
||||
alignRight () {
|
||||
const navCount = (this.$site.themeConfig.nav || []).length
|
||||
const repo = this.$site.repo ? 1 : 0
|
||||
return navCount + repo <= 2
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getPageLocalePath (page) {
|
||||
for (const localePath in this.$site.locales || {}) {
|
||||
if (localePath !== '/' && page.path.indexOf(localePath) === 0) {
|
||||
return localePath
|
||||
}
|
||||
}
|
||||
return '/'
|
||||
},
|
||||
|
||||
isSearchable (page) {
|
||||
let searchPaths = SEARCH_PATHS
|
||||
|
||||
// all paths searchables
|
||||
if (searchPaths === null) { return true }
|
||||
|
||||
searchPaths = Array.isArray(searchPaths) ? searchPaths : new Array(searchPaths)
|
||||
|
||||
return searchPaths.filter(path => {
|
||||
return page.path.match(path)
|
||||
}).length > 0
|
||||
},
|
||||
|
||||
onHotkey (event) {
|
||||
if (event.srcElement === document.body && SEARCH_HOTKEYS.includes(event.key)) {
|
||||
this.$refs.input.focus()
|
||||
event.preventDefault()
|
||||
}
|
||||
},
|
||||
|
||||
onUp () {
|
||||
if (this.showSuggestions) {
|
||||
if (this.focusIndex > 0) {
|
||||
this.focusIndex--
|
||||
} else {
|
||||
this.focusIndex = this.suggestions.length - 1
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onDown () {
|
||||
if (this.showSuggestions) {
|
||||
if (this.focusIndex < this.suggestions.length - 1) {
|
||||
this.focusIndex++
|
||||
} else {
|
||||
this.focusIndex = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
go (i) {
|
||||
if (!this.showSuggestions) {
|
||||
return
|
||||
}
|
||||
this.$router.push(this.suggestions[i].path)
|
||||
this.query = ''
|
||||
this.focusIndex = 0
|
||||
},
|
||||
|
||||
focus (i) {
|
||||
this.focusIndex = i
|
||||
},
|
||||
|
||||
unfocus () {
|
||||
this.focusIndex = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
.search-box
|
||||
display inline-block
|
||||
position relative
|
||||
margin-right 1rem
|
||||
input
|
||||
cursor text
|
||||
width 10rem
|
||||
height: 2rem
|
||||
color lighten($textColor, 25%)
|
||||
display inline-block
|
||||
border 1px solid darken($borderColor, 10%)
|
||||
border-radius 2rem
|
||||
font-size 0.9rem
|
||||
line-height 2rem
|
||||
padding 0 0.5rem 0 2rem
|
||||
outline none
|
||||
transition all .2s ease
|
||||
background #fff url(/images/search.svg) 0.6rem 0.5rem no-repeat
|
||||
background-size 1rem
|
||||
&:focus
|
||||
cursor auto
|
||||
border-color $accentColor
|
||||
.suggestions
|
||||
background #fff
|
||||
width 20rem
|
||||
position absolute
|
||||
top 1.5rem
|
||||
border 1px solid darken($borderColor, 10%)
|
||||
border-radius 6px
|
||||
padding 0.4rem
|
||||
list-style-type none
|
||||
&.align-right
|
||||
right 0
|
||||
.suggestion
|
||||
line-height 1.4
|
||||
padding 0.4rem 0.6rem
|
||||
border-radius 4px
|
||||
cursor pointer
|
||||
a
|
||||
white-space normal
|
||||
color lighten($textColor, 35%)
|
||||
.page-title
|
||||
font-weight 600
|
||||
.header
|
||||
font-size 0.9em
|
||||
margin-left 0.25em
|
||||
&.focused
|
||||
background-color #f3f4f5
|
||||
a
|
||||
color $accentColor
|
||||
|
||||
@media (max-width: $MQNarrow)
|
||||
.search-box
|
||||
input
|
||||
cursor pointer
|
||||
width 0
|
||||
border-color transparent
|
||||
position relative
|
||||
&:focus
|
||||
cursor text
|
||||
left 0
|
||||
width 10rem
|
||||
|
||||
// Match IE11
|
||||
@media all and (-ms-high-contrast: none)
|
||||
.search-box input
|
||||
height 2rem
|
||||
|
||||
@media (max-width: $MQNarrow) and (min-width: $MQMobile)
|
||||
.search-box
|
||||
.suggestions
|
||||
left 0
|
||||
|
||||
@media (max-width: $MQMobile)
|
||||
.search-box
|
||||
margin-right 0
|
||||
input
|
||||
left 1rem
|
||||
.suggestions
|
||||
right 0
|
||||
|
||||
@media (max-width: $MQMobileNarrow)
|
||||
.search-box
|
||||
.suggestions
|
||||
width calc(100vw - 4rem)
|
||||
input:focus
|
||||
width 8rem
|
||||
</style>
|
||||
@ -50,6 +50,7 @@
|
||||
<script>
|
||||
import AlgoliaSearchBox from '@AlgoliaSearchBox'
|
||||
import SearchBox from '@SearchBox'
|
||||
// import SearchBox from './BdSearchBox'
|
||||
import SidebarButton from '@theme/components/SidebarButton.vue'
|
||||
import NavLinks from '@theme/components/NavLinks.vue'
|
||||
|
||||
|
||||
@ -10,6 +10,20 @@
|
||||
<Vssue ref="vssue" :title="$page.path" :options="options"/>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
(function(){
|
||||
var bp = document.createElement('script');
|
||||
var curProtocol = window.location.protocol.split(':')[0];
|
||||
if (curProtocol === 'https') {
|
||||
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
|
||||
}
|
||||
else {
|
||||
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
|
||||
}
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(bp, s);
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@ -31,20 +31,6 @@
|
||||
<StarGazer/>
|
||||
</div>
|
||||
<div slot="page-bottom" class="bottom-description">Copyright © 2019-present 邵欢庆 <a href="http://www.eigpay.com" target="_blank">仁聚汇通</a> | 京ICP备19008693号-2
|
||||
<script>
|
||||
(function(){
|
||||
var bp = document.createElement('script');
|
||||
var curProtocol = window.location.protocol.split(':')[0];
|
||||
if (curProtocol === 'https') {
|
||||
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
|
||||
}
|
||||
else {
|
||||
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
|
||||
}
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(bp, s);
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
</ParentLayout>
|
||||
</template>
|
||||
|
||||
@ -46,20 +46,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div slot="page-bottom" class="bottom-description">Copyright © 2019-present 邵欢庆 <a href="http://www.eigpay.com" target="_blank">仁聚汇通</a> | 京ICP备19008693号-2
|
||||
<script>
|
||||
(function(){
|
||||
var bp = document.createElement('script');
|
||||
var curProtocol = window.location.protocol.split(':')[0];
|
||||
if (curProtocol === 'https') {
|
||||
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
|
||||
}
|
||||
else {
|
||||
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
|
||||
}
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(bp, s);
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
</ParentLayout>
|
||||
</template>
|
||||
|
||||
1
.vuepress/theme/search.svg
Normal file
1
.vuepress/theme/search.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#aaa" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg>
|
||||
|
After Width: | Height: | Size: 216 B |
@ -24,7 +24,7 @@ features:
|
||||
link: /learning/k8s-practice/ocp
|
||||
---
|
||||
|
||||
## 简介
|
||||
# Kuboard简介
|
||||
|
||||
Kuboard 是一款基于 Kubernetes 的微服务管理界面。
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
@ -9,4 +9,209 @@ meta:
|
||||
|
||||
# 集群级别的日志
|
||||
|
||||
正在撰写...
|
||||
Kubernetes 中并不默认提供集群级别的日志,不过,有许多种途径可以和集群级别的日志整合。例如:
|
||||
* 在每个节点上配置日志代理
|
||||
* 在应用程序的 Pod 中包含一个专门用于收集日志的 sidecar 容器
|
||||
* 从应用程序中直接推送日志到日志存储端
|
||||
|
||||
|
||||
|
||||
## 在节点上配置日志代理
|
||||
|
||||

|
||||
|
||||
如上图所示,通过在每个节点上配置一个节点级别的 logging-agent,您就可以实现集群级别的日志(cluster-level logging)。该 logging-agent 专门用来将节点上的日志文件中的日志推送到日志的后端存储。在 [节点日志的存储](./node.html#日志存储) 中,我们已经了解到,所有应用程序的标准输出都被使用 docker 的 [logging driver](https://docs.docker.com/engine/admin/logging/overview) 存储到了节点的 `/var/log/containers` 目录下(K8S 的默认配置)。因此,节点级别的 logging-agent 应该能够将该目录下的日志文件发送到日志后端。[系统组件的日志](./node.html#系统组件的日志) 可以考虑一下是否要推送到日志后端。
|
||||
|
||||
logging-agent 必须运行在每一个节点上,可以选择的实现方式有:
|
||||
* DaemonSet <Badge type="success">推荐</Badge>
|
||||
* Static Pod <Badge type="error">Deprecated</Badge>
|
||||
* 节点上的一个原生进程 <Badge type="error">Deprecated</Badge>。
|
||||
|
||||
对于 Kubernetes 集群来说,使用节点级别的 logging-agent 实现集群级别的日志(cluster-level logging)是使用最广泛也最为推荐的一种做法,因为这种做法只为每个节点创建了一个 logging-agent,且无需对节点上的容器化应用程序做任何修改。当然,只有当应用程序使用 stdout 和 stderr 记录日志时,节点级别的 logging-agent 才能生效。Kubernetes 默认安装并不指定 logging-agent,但是Kubernetes默认打包了两种 logging-agent 以供选择:
|
||||
* [Stackdriver Logging](https://kubernetes.io/docs/user-guide/logging/stackdriver) 配合 Google Cloud Platform
|
||||
* [Elasticsearch](https://kubernetes.io/docs/user-guide/logging/elasticsearch)
|
||||
|
||||
<!-- FIXME 设置 Elasticsearch 以收集日志-->
|
||||
|
||||
这两个选项都使用自定义配置了的 [fluentd](http://www.fluentd.org/) 作为节点上的 logging-agent。
|
||||
|
||||
## 在 sidecar 容器中配置 logging-agent
|
||||
|
||||
您可以按照如下方式使用 sidecar 容器,以收集日志:
|
||||
* sidecar 容器跟踪应用程序的日志文件,并输出到 sidecar 容器自己的 stdout
|
||||
* sidecar 容器运行一个 logging-agent,追踪应用程序的日志文件,并发送到日志后端
|
||||
|
||||
### sidecar输出到stdout
|
||||
|
||||

|
||||
|
||||
使用 sidecar 容器将应用程序的日志输出到 sidecar 容器自己的 `stdout` 和 `stderr` 之后,您可以直接利用已经在集群上运行的 kubelet 以及节点级别的 logging-agent 进一步将日志发送到日志后端。此时 sidecar 容器可以从日志文件读取、socket读取或者 journald 读取日志内容,其输出则是 sidecar 容器自己的 `stdout` 和 `stderr`。
|
||||
|
||||
使用这种方法:
|
||||
* 您只需要对那些不能将日志输出到 `stdout` 和 `stderr` 的应用程序进行特殊配置即可,那些已经可以将日志输出到 `stdout` 和 `stderr` 的应用程序,则可以直接利用节点级别的 logging-agent。
|
||||
* 由于重定向日志的逻辑非常简单,这种做法所带来的系统开销也是非常小的。
|
||||
* 此外,`stdout` 和 `stderr` 由 kubelet 处理,您还可以直接使用支持 apiserver 的 kubernetes 管理工具来查看日志,例如 `kubectl logs`、Kubernetes Dashboard 或 Kuboard 的日志查看界面。
|
||||
|
||||
以下面的例子为例,该 Pod 中的容器将日志记录到两个日志文件中,且两个日志文件的日志格式不一样。YAML 文件如下所示:
|
||||
|
||||
``` yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: counter
|
||||
spec:
|
||||
containers:
|
||||
- name: count
|
||||
image: busybox
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- >
|
||||
i=0;
|
||||
while true;
|
||||
do
|
||||
echo "$i: $(date)" >> /var/log/1.log;
|
||||
echo "$(date) INFO $i" >> /var/log/2.log;
|
||||
i=$((i+1));
|
||||
sleep 1;
|
||||
done
|
||||
volumeMounts:
|
||||
- name: varlog
|
||||
mountPath: /var/log
|
||||
volumes:
|
||||
- name: varlog
|
||||
emptyDir: {}
|
||||
```
|
||||
|
||||
如果将两个日志文件中完全不同的日志格式都通过一个 sidecar 容器重定向到其 `stdout` 中,最终的结果将非常混乱,你很难正确地对日志内容进行合适的处理。此时,可以考虑用两个 sidecar 容器,每个 sidecar 容器都追踪其中一个日志文件,并将日志重定向到各自的 `stdout` 中。
|
||||
|
||||
<<< @/.vuepress/public/statics/learning/logs/counter-sidecar-pod.yaml
|
||||
|
||||
* 执行如下命令以运行该 Pod
|
||||
|
||||
``` sh
|
||||
kubectl apply -f https://kuboard.cn/statics/learning/logs/counter-sidecar-pod.yaml
|
||||
```
|
||||
|
||||
* 此时,您可以通过不同的两个容器的 `stdout` 查看到想要追踪的日志文件:
|
||||
|
||||
查看第一个日志内容
|
||||
``` sh
|
||||
#执行命令
|
||||
kubectl logs conter count-log-1
|
||||
# 输出结果如下
|
||||
0: Mon Jan 1 00:00:00 UTC 2001
|
||||
1: Mon Jan 1 00:00:01 UTC 2001
|
||||
2: Mon Jan 1 00:00:02 UTC 2001
|
||||
...
|
||||
```
|
||||
查看第二个日志内容
|
||||
``` sh
|
||||
# 执行命令
|
||||
kubectl logs counter count-log-2
|
||||
# 输出结果如下
|
||||
Mon Jan 1 00:00:00 UTC 2001 INFO 0
|
||||
Mon Jan 1 00:00:01 UTC 2001 INFO 1
|
||||
Mon Jan 1 00:00:02 UTC 2001 INFO 2
|
||||
...
|
||||
```
|
||||
|
||||
此时,在无需额外配置的情况下,节点级别的 logging-agent 将自动把这些容器标准输出中的内容发送到您的日志后端。如果有必要,您也可以按照容器的不同使用不同的日志解析方法配置节点级别的 logging-agent。
|
||||
|
||||
::: tip 注意
|
||||
尽管 `logging-agent` sidecar 容器只消耗很少的 CPU 和内存(大概千分之几个 CPU 内核和几兆内存的样子),将日志写入文件,然后重定向到 `stdout`,此时再被容器引擎写入到 `/var/log/containers` 目录,这种做法仍然会消耗双倍的磁盘空间。如果您的应用程序将日志写入一个单一的文件中,更好的做法是使用 `/dev/stdout` 作为写入日志的目标,而不是使用 sidecar 容器重定向日志的方法
|
||||
:::
|
||||
|
||||
如果应用程序不能自行轮转日志文件,Sidecar 容器也可以用来轮转日志文件。例如,在一个 sidecar 容器中周期性的运行 logrotate 程序。不过,更好的办法是,直接将日志输出到 `stdout` 和 `stderr`,把日志轮转和日志保存的策略配置,交给 kubelet。
|
||||
|
||||
### sidecar容器中执行 logging-agent
|
||||
|
||||

|
||||
|
||||
如果节点级别的 logging-agent 不满足您的需要,您还可以考虑创建一个 sidecar 容器,并直接在该容器中运行一个为您的应用程序特别定制的 logging-agent。
|
||||
|
||||
::: tip 注意
|
||||
在 sidecar 容器中使用 logging-agent 可能消耗比较多的资源。此外,您也不能够使用 `kubectl logs `命令或者 Kuboard 的命令行终端查看这些日志,因为这个已经不受 kubelet 控制了。
|
||||
:::
|
||||
|
||||
下面的例子中,使用了 [Stackdriver](https://kubernetes.io/docs/tasks/debug-application-cluster/logging-stackdriver/),并配合 fluentd 作为 logging-agent。本例子提供了两个配置文件:
|
||||
* 第一个文件中包含了用于配置 fluentd 的内容
|
||||
``` yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: fluentd-config
|
||||
data:
|
||||
fluentd.conf: |
|
||||
<source>
|
||||
type tail
|
||||
format none
|
||||
path /var/log/1.log
|
||||
pos_file /var/log/1.log.pos
|
||||
tag count.format1
|
||||
</source>
|
||||
|
||||
<source>
|
||||
type tail
|
||||
format none
|
||||
path /var/log/2.log
|
||||
pos_file /var/log/2.log.pos
|
||||
tag count.format2
|
||||
</source>
|
||||
|
||||
<match **>
|
||||
type google_cloud
|
||||
</match>
|
||||
```
|
||||
* 第二个文件是一个使用 fluentd 作为 sidecar 容器的 Pod。该 Pod 挂载了上面的 ConfigMap 作为一个数据卷,fluentd 从该数据卷读取配置:
|
||||
``` yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: counter
|
||||
spec:
|
||||
containers:
|
||||
- name: count
|
||||
image: busybox
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- >
|
||||
i=0;
|
||||
while true;
|
||||
do
|
||||
echo "$i: $(date)" >> /var/log/1.log;
|
||||
echo "$(date) INFO $i" >> /var/log/2.log;
|
||||
i=$((i+1));
|
||||
sleep 1;
|
||||
done
|
||||
volumeMounts:
|
||||
- name: varlog
|
||||
mountPath: /var/log
|
||||
- name: count-agent
|
||||
image: k8s.gcr.io/fluentd-gcp:1.30
|
||||
env:
|
||||
- name: FLUENTD_ARGS
|
||||
value: -c /etc/fluentd-config/fluentd.conf
|
||||
volumeMounts:
|
||||
- name: varlog
|
||||
mountPath: /var/log
|
||||
- name: config-volume
|
||||
mountPath: /etc/fluentd-config
|
||||
volumes:
|
||||
- name: varlog
|
||||
emptyDir: {}
|
||||
- name: config-volume
|
||||
configMap:
|
||||
name: fluentd-config
|
||||
```
|
||||
|
||||
::: tip
|
||||
这个例子中使用了 Stackdriver 和 fluentd-gcp 容器,都依赖于 Google Computing Platform。实际在您的使用过程中,应该替换成您所需要的 logging-agent。
|
||||
:::
|
||||
|
||||
## 直接从应用程序容器发送日志到后端
|
||||
|
||||

|
||||
|
||||
要实现集群级别的日志,您也可以直接在每一个应用程序中将日志发送到日志后端,这种做法是 kubernetes 范围之外的,按照您通常的日志处理办法去做就可以了。
|
||||
|
||||
@ -6,7 +6,7 @@ meta:
|
||||
content: Kubernetes管理界面,K8S管理界面,Kubernetes Dashboard
|
||||
---
|
||||
|
||||
## Kuboard简介
|
||||
# Kuboard简介
|
||||
|
||||
<div style="background-color: #0063dc;">
|
||||
<div style="max-width: 363px; margin: auto;">
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
description: Kubernetes教程_以gif动图的形式形象的描述Kubernetes核心概念_本文将会简单介绍Kubernetes的核心概念_因为这些定义可以在Kubernetes的文档中找到_所以文章也会避免用大段的枯燥的文字介绍。相反,我们会使用一些图表(其中一些是动画)和示例来解释这些概念。我们发现一些概念(比如Service)如果没有图表的辅助就很难全面地理解。在合适的地方我们也会提供Kubernetes文档的链接以便读者深入学习。
|
||||
description: Kubernetes教程_以gif动图的形式形象的描述Kubernetes核心概念_本文将会简单介绍Kubernetes的核心概念_因为这些定义可以在Kubernetes的文档中找到_所以文章也会避免用大段的枯燥的文字介绍。相反,我们会使用一些图表(其中一些是动画)和示例来解释这些概念。
|
||||
---
|
||||
|
||||
# 十分钟带你理解Kubernetes核心概念
|
||||
|
||||
@ -6,7 +6,7 @@ meta:
|
||||
content: Kubernetes管理界面,K8S教程,Kubernetes教程,K8S管理界面
|
||||
---
|
||||
|
||||
## 为什么选择Kuboard
|
||||
# 为什么选择Kuboard
|
||||
|
||||
Kubernetes 已然是当下容器编排领域事实上的标准,各大云服务商都急于推出 Kubernetes 服务,互联网公司也纷纷跟进,将自己的应用容器化,并使用 Kubernetes 编排。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user